2010-09-22 11 views
19

È meglio utilizzare le code di messaggi POSIX o socket di dominio Unix per la comunicazione IPC locale?Quale è meglio per IPC locali, code di messaggi POSIX (mqueues) o socket di dominio Unix (locali)?

Ho lavorato con socket Unix tra macchine (non dominio) e ricordo che creare e interrompere la connessione avrebbe indotto i socket a fermarsi un po 'prima che finalmente se ne andassero. Inoltre, se si desidera uno scambio "affidabile" è necessario utilizzare TCP o progettare l'applicazione per restituire un ACK. Non sono sicuro se questo si applica anche ai socket di dominio Unix.

Nel mio progetto attuale abbiamo bisogno di IPC locale. La mia prima reazione è stata di usare POSIX MQueues, dal momento che li ho usati prima per la messaggistica locale. Tuttavia, un collaboratore suggerisce invece socket di dominio Unix.

Uno è migliore dell'altro o si tratta di programmare familiarità? O forse dipende dall'applicazione che si sta creando?

In una grande immagine l'applicazione su cui stiamo lavorando segue un modello client/server. I client inviano messaggi al server per "fare qualcosa". Tuttavia, il client non aspetta una risposta "fatta", sebbene voglia sapere se la richiesta è stata ricevuta o meno.

La logica di base per il lato di invio è:

connect to server 
send request 
note if the send worked or not 
disconnect from server 

Ci possono essere centinaia di clienti a quello server.

Stiamo eseguendo su un sistema SMP (4-8 core) che esegue il sistema operativo Linux.

Grazie in anticipo.

+0

Dirò ... dbus! – karlphillip

risposta

5

I socket di dominio UNIX non devono "indugiare" in uno stato TIME_WAIT -like, poiché tale tempo di attesa viene utilizzato nel caso in cui ci siano pacchetti vaganti dalla connessione che gira ancora su Internet. La preoccupazione non si applica localmente.

I socket di dominio UNIX possono essere sia SOCK_STREAM (come TCP) o SOCK_DGRAM (come UDP), con la garanzia aggiuntiva che i socket dei datagrammi del dominio UNIX sono affidabili e non riordinano i datagrammi.

Avrai ancora bisogno di un qualche tipo di ACK (lo fai anche con TCP) se vuoi essere certo che la tua altra applicazione ha letto il messaggio che hai inviato; dopotutto, anche se lo send() è riuscito, potrebbe essersi arrestato in modo anomalo prima che avesse la possibilità di elaborare il messaggio. (Questo vale anche per le code di messaggi: per essere assolutamente sicuri che un messaggio non vada perso, l'applicazione di ricezione deve scrivere la richiesta su un giornale, svuotarla sul disco e quindi inviare una conferma).

Sono d'accordo che la scelta è essenzialmente una questione di familiarità di programmazione.

4

Uno è migliore dell'altro, o si tratta di programmare familiarità? O forse dipende dall'applicazione che si sta creando?

code di messaggi SysV rispetto a UNIX socket dominio datagram hanno le maggiori differenze io sappia:

  • È possibile poll() presa, ma non è possibile coda di messaggi.

  • La coda di messaggi è globale e potrebbe (e di solito lo richiede) richiedere un intervento amministrativo: la pulizia di vecchie risorse SysV sospese è una delle numerose routine quotidiane di sysadmin. Mentre la semantica del dominio UNIX è molto più semplice e le applicazioni possono generalmente mantenerla completamente internamente senza il coinvolgimento del sysadmin.

  • (?) La coda di messaggi è persistente, potrebbe conservare i messaggi dalle sessioni precedenti. (Non riesco a ricordare quel bit con precisione, ma l'IIRC mi stava succedendo più di una volta).

  • Guardando allo man msgrcv non vedo l'analogo di socket MSG_PEEK. Raramente necessario, ma a volte è abbastanza utile.

  • Nella maggior parte dei casi, gli utenti preferiscono utilizzare i nomi simbolici della configurazione, non l'ID della chiave numerica. La mancanza di chiavi simboliche IMO è una supervisione piuttosto grave su parte dei progettisti dell'interfaccia SysV.

Come tutte le risorse SysV, la loro gestione è il principale PITA. Se lasci che il sistema decida l'ID della coda dei messaggi, devi occuparti di condividerli correttamente con altre applicazioni. (E devi anche dire agli amministratori in qualche modo che l'ID deve essere rimosso alla fine). Se si consente di configurare la chiave per la coda messaggi, è possibile che si verifichino problemi banali che l'ID sia già utilizzato da qualche applicazione o che sia un residuo dell'esecuzione precedente. (Vedere il riavvio dei server solo perché esauriscono le risorse SysV è piuttosto comune.)

Tutto sommato, evito le risorse SysV quando possibile: la mancanza del supporto poll() nelle circostanze più comuni è un interruttore.

Tuttavia, il client non attende una risposta "fatta", sebbene voglia sapere se la richiesta è stata ricevuta o meno.

Questo è un dilemma comune dell'elaborazione transazionale. La risposta generale è (come in RDBMS) non è possibile e dopo l'interruzione della comunicazione (arresto anomalo o qualsiasi altra cosa) l'applicazione deve verificare se la richiesta è già stata elaborata o meno.

Da quello posso dire che probabilmente TCP sarebbe una scelta migliore. Il client invia la richiesta e la dichiara terminata solo quando riceve una risposta positiva dal server. Il server, a meno che non sia in grado di inviare la risposta al client, deve eseguire il rollback della transazione.

+2

Tuttavia, su Linux un descrittore di coda di messaggi posix è in realtà un descrittore di file e supporta select/poll. Non sono sicuro delle code dei messaggi sysv. – nos

+0

@nos: riferimento? non lo stai mescolando con AIX? POSIX non lo descrive e il [vecchio riferimento Linux che conosco] (http://www.steve.org.uk/Reference/Unix/faq_3.html#SEC31) dice anche no. – Dummy00001

+2

man mq_overview, "Su Linux, un descrittore di coda di messaggi è in realtà un descrittore di file e può essere monitorato utilizzando select (2), poll (2) o epoll (7) .Questo non è portabile." , come accennato si tratta di code di messaggi posix, non sono sicuro che se i messaggi di sistema sysv funzionino in questo modo, se lo fanno è cambiato negli ultimi anni. – nos

3

Suggerirei di consultare DBus per un'applicazione di questo tipo, se non altro per il loro marshalling dati e l'interfaccia simile a RPC (sia sincrona che asincrona). Utilizza i socket di dominio in modo nativo e funziona davvero bene dopo una curva di apprendimento iniziale.