Jaki waszym zdaniem jest najwydajniejszy sposób komunikacji dwóch programów napisanych w różnych językach programowania?

2

Powiedzmy że mam dwie aplikacje napisane w zupełnie różnych językach programowania, dajmy C++ i Python. Albo Java i JavaScript. Założenie jest takie że nie można odpalić jednego w drugim (jakby się dało np Kotlin i Groovy).

W jaki sposób można na jednej maszynie uruchomić takie dwie aplikacje, tak żeby się mogły komunikować?

  1. Wiadomo, niby-microserwis i komunikacja po TCP/IP, czyli pewnie HTTP - ale to może być trochę wolne, nawet na tej samej maszynie.
  2. Jeśli możemy korzystać z OS to można wysłać komunikat systemowy, np łapiąc hWND na Windowsie; ale nie wiem jak to się ma do requestu po sieci.
  3. Pośrednik, np redis/kafka?
  4. Podpięcie jednego pod kanały drugiego, i komunikacja używając wyjść standardowych?

Inne pomysły?

Priorytetem jest wydajność, a dokładniej mówiąc "lag" pomiędzy wysłaniem i odebraniem.

4

GraalVM :]

4

Standardowe mechanizmy komunukacji między procesami: shared memory, queues, named pipes, sockety po loopbacku.

4
yarel napisał(a):

sockety po loopbacku.

lokalnie tcp/ip? jeśli tak, to przesada, bo są unix sockets, np: https://openjdk.java.net/jeps/380

For local, inter-process communication, Unix-domain sockets are both more secure and more efficient than TCP/IP loopback connections.
(...)
Unix-domain sockets have long been a feature of most Unix platforms, and are now supported in Windows 10 and Windows Server 2019.

3

To zaelży od sytuacji. Dla prostych i szybkich rozwiązań, w obrębie jednej maszyny, wystarczą strumienie. Przy statycznej strukturze wystarczą standardowe strumienie, chyba że standardowe strumienie są już do czegoś używane, lub nie przewidujemy uruchamiania obu programów na raz, lub mamy zamiar używać wielu różnych klientów — wtedy strumienie nazwane. Jeśli komunikujemy się między dwoma maszynami to w zależności od przypadku HTTP lub Kafka. Wiadomo, HTTP dla bardziej dynamicznego połączenia na żądanie, a Kafka dla statycznej struktury, zwykle dla większej ilości mikroserwisów, zwłaszcza wymagających dużej przepustowości.

1
TomRiddle napisał(a):

Powiedzmy że mam dwie aplikacje napisane w zupełnie różnych językach programowania, dajmy C++ i Python. Albo Java i JavaScript. Założenie jest takie że nie można odpalić jednego w drugim (jakby się dało np Kotlin i Groovy).

Python bardzo ładnie się integruje z C++, jest to oficjalnie udokumentowane wiec żaden hacking. Dokładnie ten sam C-Python
Javascript się odpalał z Javy w postaci silników Rhino i innych, trochę się to zdezaktualizowało, ale warto sprawdzić.

Wiadomo, niby-microserwis i komunikacja po TCP/IP, czyli pewnie HTTP - ale to może być trochę wolne, nawet na tej samej maszynie.

Alternatywą do świętego HTTP/REST-a są binarne protokoły RPC, Google Protocol Buffer, Apache Thrift i jeszcze kilak innych by znalazł.

6

Najlepiej gRPC - ale to armata. Polaczysz wszystko ze wszystkim na zasadzie RPC (wywołanie procedur), oparte na HTTP/2.

Do kolejkowania wybierz jakis standard (ale nie JMS) albo popularna darmowa kolejke - np ZeroMQ lub ActiveMQ. Redis i Kafka tez sie nadadza.

Mechanizmy IPC wyzej wymienione maja te zalete ze nie wymagaja instalacji dodatkowego softu ale za to musisz miec do tego biblioteki i nie do każdego języka sa dostepne, przy IPC bedzie wiecej swojego kodowania.

Najgorsze co mozesz zrobic to integracja przez bazę danych.

Najprościej zintegrować przez RESTa, ale to moze byc za wolne.

0
vpiotr napisał(a):

Najlepiej gRPC - ale to armata. Polaczysz wszystko ze wszystkim na zasadzie RPC (wywołanie procedur), oparte na HTTP/2.

  1. Dlaczego armata? Harmonijnie zaprojektowane, najwyżej pistolet maszynowy.
  2. HTTP nie jest preferowanym protokołem "backendowym", jest opcją.
6

Najprostszym sposobem są pliki (uniksowe) otwarte w trybie nieblokującym, np. potoki. HTTP czy systemy kolejkowe powodują pewien narzut czasu odpowiedzi - większy, niż w przypadku mechanizmów systemowych. Co innego w przypadku większej liczby procesów.

1
PerlMonk napisał(a):

Najprostszym sposobem są pliki (uniksowe) otwarte w trybie nieblokującym, np. potoki. HTTP czy systemy kolejkowe powodują pewien narzut czasu odpowiedzi - większy, niż w przypadku mechanizmów systemowych. Co innego w przypadku większej liczby procesów.

Odpowiedź na pytanie z wątku jest dwupoziomowa. Trochę chaosu z tego powodu jest w tym wątku.

Surowy protokół "nośnik" (niechby były przykładowe pipy, być może lżejsze niż TCP, nie wnikam), i implementacja np serializacja użytecznych danych.

Ja osobiście mocno sympatyzuję inteligentnym protokołom binarnym, mniej CPU, mniej GC (w językach z GC)

1

ja używałem udp z loopback. Nawet po odłączeniu karty sieciowej wszystko działało. i nie trzeba znać ip urządzenia.

6

Potencjalnie shared memory (shmget).

1

Najwydajniejszy do IPC? Pewnie memory mapped files.

3
TomRiddle napisał(a):
  1. Wiadomo, niby-microserwis i komunikacja po TCP/IP, czyli pewnie HTTP - ale to może być trochę wolne, nawet na tej samej maszynie

@TomRiddle: Dlaczego uważasz że jak TCP/IP to od razu HTTP?

3

Jeśli chodzi o wydajność rozumianą "co będzie działało najszybciej" to wspólny obszar w pamięci - ale tutaj schodzi się naprawdę nisko, trzeba uwspólnić miejsca w pamięci a pewnie nie każdy język ma bezproblemowe wsparcie dla takich rzeczy.
Jeśli chodzi o taką standardową komunikację po socketach to pewnie najbardziej wydajny byłby własny protokół, skrojony na miarę.

5

Warto się zastanowić nad modelem (a nie mechanizmem) samej komunikacji, tj. ile procesów będzie uczestniczyć w takiej komunikacji, w którą stronę będzie zachodzić i jak ma wyglądać synchronizacja.

W przypadku SHM, segment pamięci współdzielonej tworzony jest raz i procesy mapują sobie ten segment do swojej przestrzenie adresowej, późniejsze zapisy i odczyty są bezpośrednio do pamięci, więc bedzie to szybsze niż przechodzenie przez warstwy systemowe, które obsługują operacje read/write (czy to na sokecie, czy na pliku). Synchronizacja jednak będzie dalej potrzebna (np. semafor do zapewnienie bezpiecznych zapisów i odczytów i nie ucieknie się od systemcalla).

0
kamil kowalski napisał(a):

ja używałem udp z loopback. Nawet po odłączeniu karty sieciowej wszystko działało. i nie trzeba znać ip urządzenia.

Z UDP mogą być straty i nie ma gwarancji że dojdą pakiety w dobrej kolejności nawet na lokalu

PerlMonk napisał(a):

Najprostszym sposobem są pliki (uniksowe) otwarte w trybie nieblokującym, np. potoki.

Ale to daje narzut systemu plików, nie jestem pewien czy to faktycznie takie szybkie.

4
TomRiddle napisał(a):
PerlMonk napisał(a):

Najprostszym sposobem są pliki (uniksowe) otwarte w trybie nieblokującym, np. potoki.

Ale to daje narzut systemu plików, nie jestem pewien czy to faktycznie takie szybkie.

Zwykłe pliki (regular file) znajdujące się na dysku faktycznie mogą być wolniejsze. Jeśli nawet wydajność dobrego SSD nie wystarcza, to pozostają potoki. Co prawda potoki i sockety są reprezentowane przez ścieżkę w systemie plików, to nie są zwykłymi plikami. Przy otwieraniu sprawdzane są uprawnienia itp., ale to dzieje się tylko raz. Potem możesz pisać i czytać niemal swobodnie. Pod spodem nie ma wtedy żadnego pliku.

1
PerlMonk napisał(a):
TomRiddle napisał(a):
PerlMonk napisał(a):

Najprostszym sposobem są pliki (uniksowe) otwarte w trybie nieblokującym, np. potoki.

Ale to daje narzut systemu plików, nie jestem pewien czy to faktycznie takie szybkie.

Zwykłe pliki (regular file) znajdujące się na dysku faktycznie mogą być wolniejsze. Jeśli nawet wydajność dobrego SSD nie wystarcza, to pozostają potoki. Co prawda potoki i sockety są reprezentowane przez ścieżkę w systemie plików, to nie są zwykłymi plikami. Przy otwieraniu sprawdzane są uprawnienia itp., ale to dzieje się tylko raz. Potem możesz pisać i czytać niemal swobodnie. Pod spodem nie ma wtedy żadnego pliku.

Nie chodzi o to czy wystarczy czy nie wystarcza, tylko po co zapisywać i odczytywać na dysku to coś.

1

Jeśli jedna maszyna to nie da się lepiej niż dzielona pamięć. A jak chcesz czegoś "czystszego" to masz unixowe sockety https://github.com/rigtorp/ipc-bench

0

W IPC masz m.in. potoki, potoki nazwane i pamięć współdzieloną.

Oprócz tego masz jeszcze unixowe kolejki, ale mi średnio działały (podobnie jak z potokami stan ich uruchomienia byl u mnie niestabilny - chyba zalezy od typu OS -BSD, Linux, Mac moga dzialac roznie).

https://linuxhint.com/posix-message-queues-c-programming/

0

Redis, Cloudi,

2

(redis) Pomiędzy różnymi maszynami może jest to wygodne rozwiązanie, ale na jednej maszynie? — Shalom 38 minut temu

Po raz kolejny wątek zmienia front z fizycznego protokołu na usługę (a @donPietro tego nie dopowiedział )

Redis jest ciekawy jako mega-usługa, może być cache, kolejką i kilkoma rzeczami jeszcze
To MOŻE być wartościowe w projekcie, ale tego nie wiemy (np w szybkiej rozmowie niby nie potrzebujemy krótkiego przechowania danych jakiś czas, ale jednak po analizie przyda się). Hipotetycznie: szybki komunikat o zmianie w kolejce, ale struktura danych żyjąc dłużej. Póki co gdybanie.

@TomRiddle:

A tak naprawdę, to o jakich liczbach mowa w Twoim pytaniu?
Co to naprawdę mam być?
Preferfencje pomiędzy złożonością logiczną a nanosekundami ?

0
ZrobieDobrze napisał(a):

Co to naprawdę mam być?
Preferfencje pomiędzy złożonością logiczną a nanosekundami ?

Jakąkolwiek by ta złożoność nie była, to to szczegół implementacyjny.

1 użytkowników online, w tym zalogowanych: 0, gości: 1