2012-12-13 11 views
6

Possiedo un'applicazione che necessita periodicamente di inviare un'istantanea del suo stato corrente, che attualmente verrebbe rappresentata da circa 500.000 messaggi a 64 byte. Ho avuto difficoltà ad ottenere questo numero di messaggi inviati e ricevuti in modo rapido e affidabile utilizzando ZMQ.Quali sono le impostazioni appropriate per ZMQ quando si inviano messaggi 500K a 64 byte?

Ho utilizzato PUB/SUB su TCP per farlo al momento, ma non sono compatibile con il pattern o il protocollo fintanto che il lavoro verrà completato. Nei miei esperimenti mi sono concentrato a giocare con l'invio e ricevere l'high water mark, inviare e ricevere le impostazioni del buffer e aggiungere alcuni sleep al ciclo di invio per cercare di rallentarlo un po '. Con impostazioni che mi sembravano abbastanza generose (500K HWM, 10 MB di buffer) e che usavano solo una connessione di loopback, i messaggi non vengono ancora tutti ricevuti in modo consistente.

Sono interessato a quali sono le impostazioni appropriate per questi o altri parametri di ottimizzazione, e più in generale su come ragionare sull'effetto che avranno le varie impostazioni.

Alcuni ulteriori dettagli che possono contribuire a fornire una risposta adeguata:

  • La distribuzione è uno a molti. Il numero previsto di destinatari è di circa 20.

  • Ogni messaggio rappresenta un insieme di informazioni su un diverso strumento finanziario, tutte osservate contemporaneamente. Nella mia mente si possono fare discussioni sia per combinarli in un unico grande messaggio (l'insieme di tutti i messaggi crea logicamente un'istantanea completa) sia per tenerli separati (i clienti potrebbero essere potenzialmente interessati solo ad alcuni strumenti, e penso che ciò aiuterebbe filtrarli più facilmente).

  • La frequenza prevista dei messaggi è fondamentalmente non più veloce di 20 millisecondi e non più lenta di 5 secondi. Il punto in cui atterrerò sarà probabilmente influenzato da considerazioni sulle prestazioni (ovvero, quanto velocemente il mio server può effettivamente pompare i messaggi e quale tipo di velocità dei dati si rivelerebbe travolgente per i client).

+0

Qual è la tua distribuzione? 1 a 1, uno a molti, uno dei tanti? Quanto spesso stai inviando lo stato? State davvero pubblicando uno stato di 32 MB? Perché inviarlo come 500K singoli messaggi? Perché non un messaggio? Qual è il ragionamento? Si prega di spiegare il caso d'uso in modo più dettagliato, se si desidera risposte utili. –

risposta

1

Dopo una giornata di sperimentare semi-casualmente con varie combinazioni, sono venuto alle seguenti conclusioni provvisorie:

  • Aggiunta di comandi di pausa nel mio loop send per limitare la frequenza dei messaggi migliora l'affidabilità con praticamente qualsiasi serie di opzioni.

  • L'invio di 500.000 messaggi come frame di un singolo messaggio invece di 500K singoli messaggi migliora l'affidabilità.

  • L'utilizzo dell'epgm anziché del protocollo tcp consente di ottenere un throughput più elevato.

  • Con epgm, l'opzione di velocità multicast deve corrispondere alla velocità di messaggio desiderata ottenuta dalle istruzioni di sospensione.

  • L'aumento del limite massimo di acqua e dei buffer aiuta l'affidabilità, ma è necessario aumentare entrambe le impostazioni e farlo sul client e sul server. Se non si fanno tutti insieme, tende a non aiutare. Devi impostarli abbastanza in alto per ottenere qualsiasi tipo di affidabilità in esecuzione con i singoli messaggi (al contrario dei frame di un singolo messaggio). In questo caso, non ho ottenuto buoni risultati fino a quando non ho avuto i punteggi di alta marea impostati su 1.000.000 e i buffer impostati su 65 MB. (Due volte la dimensione del set di messaggi che stavo cercando di inviare.) Questo era molto più alto di quanto pensassi istintivamente di provare.Quel caso stava facendo una pausa di 5 secondi tra ogni round di 500K messaggi. Portando l'intervallo a 1 secondo, ho dovuto spingerli ancora più in alto, a 4 volte la dimensione di un singolo gruppo di messaggi.

  • Con epgm, l'impostazione dell'intervallo di ripristino non è di grande aiuto.

+0

Sono ancora interessato a capire meglio perché le impostazioni funzionano come fanno. Prenderò in considerazione una risposta che ha fatto un buon lavoro nel spiegare perché le varie impostazioni hanno aiutato o non hanno avuto il meglio delle mie. – scott

5

Rompiamo questo.

primo luogo, perché la HWM non "funziona":

L'HWM non è un limite preciso, poiché buffer interni vengono riempite e svuotate da due fili separati, e il conteggio di spazio disponibile può ritardo piuttosto una molto quando c'è molta attività. La pagina man zmq_setsockopt 0MQ dice, "0MQ non garantisce che il socket accetterà un numero di messaggi ZMQ_SNDHWM e il limite effettivo potrebbe essere inferiore del 60-70% a seconda del flusso dei messaggi sul socket."

In secondo luogo, i messaggi perché stai perdendo:

Come si dump messaggi 0.5M (x 20) nel buffer dei socket, si casualmente colpito all'HWM e il comportamento della presa del PUB poi è far cadere i messaggi che non posso fare la coda.

In terzo luogo, come risolvere questo:

C'è lo zero motivo per rompere lo stato in messaggi separati; l'unica logica per questo sarebbe se lo stato non si adattava alla memoria, cosa che fa facilmente. Invia come multipart (ZMQ_SNDMORE); questo crea un singolo messaggio efficace che prende 1 slot nel buffer in uscita.

Quindi, rimuovere il limite di 500K HWM e ripristinare il valore predefinito (1000) che sarà più che sufficiente.

In quarto luogo, come ottenere una migliore performance:

Ovviamente, il profilo e migliorare il vostro editore e il codice abbonato possibile; questi sono i soliti colli di bottiglia.

Quindi, considera una forma di compressione sul messaggio se è sparsa e puoi farlo senza troppi costi della CPU. Con 20 abbonati, di solito si guadagna di più dall'overhead della rete di quanto si perderà dal costo della CPU.

Infine, se si aumenta a un numero maggiore di abbonati e si tratta di un sistema critico, consultare PGM multicast, che rimuoverà efficacemente i costi di rete.

+0

Se rompo lo stato in messaggi separati, posso filtrarli sul lato client con ZMQ_SUBSCRIBE, corretto? È possibile quando li invii come frame all'interno dello stesso messaggio? – scott

Problemi correlati