PDA

View Full Version : [C#] Libreria IPC basata su Message Passing


fano
12-03-2017, 19:30
Ciao a tutti!

Noi sviluppiamo applicazioni su Architettura Distribuita e quindi spesso usiamo processi quando in un'applicazione moderna si userebbero thread... il tutto è scritto in C (:cry:), con 2 demoni che rompono le palle più che altro e i processi sono creati con la classica fork() / exec().

Il mio sogno sarebbe di passare a C# e - con la scusa - usare qualcosa di più moderno... ma il fatto che esistono più processi per fare le cose mi interessa mantenerlo sia perché ho bisogno che l'applicazione possa essere divisa su più macchine sia perché è comodo magari per il collega sviluppare una parte e farsi la sua mini "applicazione" senza quello che sto sviluppando io e che magari ancora non funziona.

Così questo sarebbe quello che mi piacerebbe avere:


Lo scambio deve avvenire con dei messaggi, la libreria non dovrebbe avere alcun interesse al contenuto, ma solo trovare il processo / destinatario e inviargli il messaggio
La libreria non deve imporre il suo formato di serializzazione per esempio devo poter passare da Json a MessagePack senza minimamente toccare il mio codice, ma semplicemente cambiando la configurazione. WCF quindi non va bene perché usa XML come formato di serializzazione
La versione originale della libreria nel classico stile Unix anni '50 usava i socket per comunicare tra i processi, ci siamo accorti ben presto che per il nostro uso era troppo lenta la rete e così passammo alle real time queue... mantenendo la rete per il raro caso in cui il processo giri su un'altra macchina. Ecco la libreria che ciò sto cercando dovrebbe essere "furba" nello stesso modo usare il sistema di comunicazione più veloce se sono sulla stessa macchina e usare la rete solo nel caso in cui il processo sia remoto
Non deve essere richiesto di fare configurazioni strane, avere server / demoni tra i piedi o altro... deve funzionare e basta!
La comunicazione tra i processi deve essere quasi istantanea per intenderci > 10 ms e siamo morti :cry:
Essendo in C# mi aspetto che funzioni ovunque (pure su Cosmos in futuro ovviamente :Prrr:)
Plus che con l'attuale libreria un thread non può ricevere messaggi, in alcuni casi sarebbe utile farlo ovviamente i messaggi li potrebbe ricevere solo dal thread main o da altri thread suoi fratellini (per quanto se le queue esistono a livello di kernel e sono "file"...)
Plus se quando cade la connessione di rete salva i messaggi da qualche parte per poi spararli tutti in una volta quando la connessione ritorna


Quindi una cosa del genere esiste già? O me la devo fare da solo?

tomminno
13-03-2017, 14:27
Che io sappia, i meccanismi IPC inclusi in .Net sono wrapper su funzioni esposte dall'OS (socket, named pipe, mmf).

WCF è una tecnologia (ormai obsoleta) per webservice SOAP, quindi è un meccanismo di comunicazione basato su socket. Ad oggi meglio Asp.Net MVC Core.

Come funziona in COSMOS la comunicazione IPC? :D

fano
13-03-2017, 17:46
Che io sappia, i meccanismi IPC inclusi in .Net sono wrapper su funzioni esposte dall'OS (socket, named pipe, mmf).


Beh sì questo è ovvio! Lo pipe se sono come su Linux hanno il problema che hanno una dimensione schiantata e NON modificabile e quando si riempono si blocca tutto :muro:
Le real time queue sono configurabili per numero massimo di messaggi e dimensione massima di ogni messaggio, inoltre puoi fare in modo che quando la coda è piena o si blocca chi scrive (fino a che chi legge scoda) o si iniziano a cacciare nel c*sso i messaggi!

Abbiamo "risolto" mettendo numero enormi... in un'applicazione real time in ogni caso se il ricevente non scoda abbastanza velocemente sei nella brilla :D

Il socket come ho detto sopra quando i processi si trovano sulla stessa macchina è meglio evitarli...

L'unica "wrapper" che ho visto simile come concetto alle code real time è questo:
https://msdn.microsoft.com/en-us/library/system.messaging%28v=vs.110%29.aspx

però non se esiste nulla ad alto livello e soprattutto Mono le supporterà?


WCF è una tecnologia (ormai obsoleta) per webservice SOAP, quindi è un meccanismo di comunicazione basato su socket. Ad oggi meglio Asp.Net MVC Core.


Però tipicamente le mie applicazioni non hanno nulla a che fare con WEB, acquisiscono eventi "real time", li processano, a volte c'è anche un operatore che smanazza su una GUI fatta comunque come fosse un'applicazione desktop (attualmente su Linux usiamo Qt... un disastro)...


Come funziona in COSMOS la comunicazione IPC? :D


Per ora non abbiamo ancora il multi processing comunque su un SO come Cosmos in cui i processi saranno molto probabilmente "thread" sarà molto semplice fare IPC una volta trovato il "ricevente" potrai chiamare direttamente la sua "Recv()" dandogli l'ownership dell'oggetto "Message" ovvero senza dover serializzare nulla e senza copie :D

P.S. MessageQueue impone serializzazione in XML quindi è da scartare...

tomminno
14-03-2017, 14:10
Beh sì questo è ovvio! Lo pipe se sono come su Linux hanno il problema che hanno una dimensione schiantata e NON modificabile e quando si riempono si blocca tutto :muro:
Le real time queue sono configurabili per numero massimo di messaggi e dimensione massima di ogni messaggio, inoltre puoi fare in modo che quando la coda è piena o si blocca chi scrive (fino a che chi legge scoda) o si iniziano a cacciare nel c*sso i messaggi!

Abbiamo "risolto" mettendo numero enormi... in un'applicazione real time in ogni caso se il ricevente non scoda abbastanza velocemente sei nella brilla :D


Ma quindi usate già una coda Real Time? E cosa state usando?


Il socket come ho detto sopra quando i processi si trovano sulla stessa macchina è meglio evitarli...


"Applicazione distribuita" e "stessa macchina" sono antitetici :ciapet:
Non vedo molte altre alternative: o Named Pipe o Memory Mapped File.


L'unica "wrapper" che ho visto simile come concetto alle code real time è questo:
https://msdn.microsoft.com/en-us/library/system.messaging%28v=vs.110%29.aspx

però non se esiste nulla ad alto livello e soprattutto Mono le supporterà?


E' un wrapper per MSMQ quindi disponibile solo su Windows, non ho idea se esista qualcosa di compatibile su Linux.


Però tipicamente le mie applicazioni non hanno nulla a che fare con WEB, acquisiscono eventi "real time", li processano, a volte c'è anche un operatore che smanazza su una GUI fatta comunque come fosse un'applicazione desktop (attualmente su Linux usiamo Qt... un disastro)...


Ma hai veramente requisiti real time? Perchè in tal caso mi pare veramente strano realizzare un'applicazione distribuita che poi lavora sulla stessa macchina. Generalmente in sistemi Real Time si vanno a fare i conti al millisecondo (o peggio) per il tempo a disposizione per la computazione e da lì si parte per realizzare un'algoritmo che completi in ogni modo entro il tempo previsto.

Il fatto che si chiamino webservice non significa che siano applicabili solo all'ambito web :D
Qt nella versione widget a volte sono un po' legnose, ma un disastro proprio? :mbe:


Per ora non abbiamo ancora il multi processing comunque su un SO come Cosmos in cui i processi saranno molto probabilmente "thread" sarà molto semplice fare IPC una volta trovato il "ricevente" potrai chiamare direttamente la sua "Recv()" dandogli l'ownership dell'oggetto "Message" ovvero senza dover serializzare nulla e senza copie :D

P.S. MessageQueue impone serializzazione in XML quindi è da scartare...

Quindi ogni processo/thread avrà accesso alla memoria di tutti gli altri? :stordita:

fano
17-03-2017, 08:44
Ma quindi usate già una coda Real Time? E cosa state usando?


Su Linux usiamo Posix Message Queue:
http://man7.org/linux/man-pages/man7/mq_overview.7.html


"Applicazione distribuita" e "stessa macchina" sono antitetici :ciapet:


Perché? La nostra "applicazione" è formata da più processi sia che si trovi tutto su una macchina sia che si trovino su più di una!

L'architettura attuale ha 3 difetti:

1. Usando Posix Message Queue funziona solo su Linux / Unix
2. E` scritta in C (:cry:)
3. Ha 2 processi "demoni" che servono di fatto solo per il caso (raro per altro) in cui l'applicazione sia distribuita su più macchine (solo in quel caso tra i "demoni" la comunicazione avviene su rete)


Non vedo molte altre alternative: o Named Pipe o Memory Mapped File.


Ma le Named Pipe non hanno gli stessi problemi che su Unix / Linux? Ovvero che hanno una limitazione arbitraria sulla dimensione del messaggio e sul numero massimo di messaggi?


E' un wrapper per MSMQ quindi disponibile solo su Windows, non ho idea se esista qualcosa di compatibile su Linux.


In ogni caso non è la soluzione visto che impone XML come formato di serializzazione, siamo rimasti scottati in passato per aver usato la soluzione sbagliata (come json, sqlite, i socket) quindi voglio un sistema più modulare in cui posso sostituire il sistema di message packing o il DB (usando Entity Framework o NHibernate).


Ma hai veramente requisiti real time? Perchè in tal caso mi pare veramente strano realizzare un'applicazione distribuita che poi lavora sulla stessa macchina. Generalmente in sistemi Real Time si vanno a fare i conti al millisecondo (o peggio) per il tempo a disposizione per la computazione e da lì si parte per realizzare un'algoritmo che completi in ogni modo entro il tempo previsto.


In realtà solo alcune parti dell'applicazione hanno requisiti real time, il resto tipo interfaccia utente, driver di una stampante non hanno questi problemi...

Comunque sì in molti casi riusciamo a fare tutta l'elaborazione in 10 ms, spesso è il SO (Linux) che "combatte" contro i nostri requisiti real time visto che a volte schedula processi che NON dovrebbe (togliere la CPU al processo Real Time per far girare la rotella sulla GUI non è proprio il massimo :Prrr:).


Il fatto che si chiamino webservice non significa che siano applicabili solo all'ambito web :D


Certo! Però la rete ci fregava proprio noi leggevamo dal sensore quando ormai l'evento era bello che finito gli mandavamo la risposta, ma non era più lì :D


Qt nella versione widget a volte sono un po' legnose, ma un disastro proprio? :mbe:


Usiamo la versione QML per me il fatto che non ci sia un designer decente e che si debbano fare rettangoli uno dentro l'altro per "simulare" il layout è già sufficiente :eek:
Poi è uno Widget Tool Kit incompleto per fare i bottoni con il bordo rotondo ce li siamo dovuti riscrivere completamente, mancano form (!), messagebox e persino i menu... boh!
Purtroppo è una scelta aziendale obbligatoria quindi continuiamo a subire finché - spero - non si rendano conto che è una c*gata!


Quindi ogni processo/thread avrà accesso alla memoria di tutti gli altri? :stordita:

Di fatto sì poi visto che vogliamo essere compatibili con il vero C# (qualunque programma C# funzionerà su Cosmos) un "processo" potrà accedere solo alla sua memoria e a quella che il kernel gli concede di vedere per esempio quando deve leggere un file molti passaggi che un normale OS farebbe si saltano (zero copy I/O), Message Passing è un altro di questi casi (non c'è una vera "send()" il riferimento al messaggio è passato direttamente all'altro "processo").

La "protezione" all'accesso di memoria avviene tutto con C# perché Cosmos è un Managed Operating System :D

Come Singularity e Midori per l'appunto...

fano
24-03-2017, 09:20
Sto un po' giocando con MessagePack rispetto al C/C++ e le ridicole strutture (con il packing, l'endianess, ...) è proprio un altro mondo: creare oggetti e deserializzarli con 2 colpi di mouse non ha prezzo :D

Ce ne sono 2 librerie MessagePack per C#:
1. https://github.com/neuecc/MessagePack-CSharp
2. https://github.com/msgpack/msgpack-cli

la seconda è realizzata dall'ideatore originale del protocollo (lo stesso che ha fatto MessagePack per praticamente tutti gli altri linguaggi) ed è pure quella con più download, ma la sconsiglio ha ENORMI problemi di performance per serializzare un oggetto pure piuttosto semplice, mi è stato 1.250 secondi :eek:
Non ha nemmeno supporto visto che non risponde alle issues, l'altra è quindi meglio: a serializzare lo stesso oggetto ci sta 30 millisecondi!

Resta aperto il discorso che cosa uso per far comunicare sti processi?