2009-08-28 15 views
17

Sto provando RabbitMQ con this collegamento Python.Come impostare il rilevamento del timeout su un server RabbitMQ?

Una cosa che ho notato è che se uccido un utente non pulito (emulando un programma bloccato), il server penserà che questo utente è ancora lì da molto tempo. Il risultato di questo è che ogni altro messaggio verrà ignorato.

Per esempio, se si uccide un tempo di consumo 1 e ricollega, poi 1/2 messaggi verranno ignorati. Se uccidi un altro utente, i 2/3 messaggi verranno ignorati. Se uccidi un terzo, i messaggi 3/4 saranno ignorati e così via.

Ho provato ad attivare i riconoscimenti, ma non sembra essere d'aiuto. L'unica soluzione che ho trovato è quella di arrestare manualmente il server e resettarlo.

C'è un modo migliore?

come ricreare questo scenario

  • Run RabbitMQ.

  • Annulla archiviazione this library.

  • Scarica il consumatore ed editore here. Eseguire amqp_consumer.py due volte. Esegui amqp_publisher.py, inserendo alcuni dati e osservando che funziona come previsto. I messaggi vengono ricevuti in stile round robin.

  • Uccidi uno dei processi di consumo con kill -9 o task manager.

  • Ora, quando si pubblica un messaggio, il 50% dei messaggi saranno persi.

+0

Ho aggiornato la mia risposta. –

+0

Non riesco a riprodurre questo. Quale versione di linux stavi usando –

+3

Buona domanda - questo è un problema critico se si esegue dietro un firewall o un dispositivo di bilanciamento del carico IP che cade i socket inutilizzati dopo N secondi, perché né RabbitMQ né il client saranno mai informati che il socket è andato via fino a quando non provano ad usarlo. –

risposta

2

Si prega di fornire alcune ulteriori specifiche riguardanti i componenti che hai dichiarato. Di solito (ed indipendente della realizzazione client) una coda con le proprietà

  • esclusivi e
  • Autoeliminazione

dovrebbe ottenere rimosso non appena la connessione tra il client dichiarare e il broker si rompe. Questo però non ti aiuterà con le code condivise. Per favore, spiega un po 'cosa stai cercando di modellare.

+0

Non sto parlando di quando le code vengono cancellate. Sto parlando di come rabbitmq non rilevi connessioni interrotte per un tempo molto lungo e continua a cercare di inviare messaggi come se fossero ancora lì. – Unknown

5

RabbitMQ non ha un timeout sui riconoscimenti da parte del client che un messaggio è stato elaborato: vedere this post (l'intero thread potrebbe essere di interesse). Alcuni punti salienti da posta:

L'AMQP modello di ACK per abbonamenti e "pull" sono identiche. In entrambi i casi il messaggio viene mantenuto sul server ma non è disponibile per altri utenti fino a quando non è stato bloccato (e rimosso), nack (con base.rifiutare; anche se RabbitMQ non lo implementa) o il canale/connessione è chiuso (al punto il messaggio diventa disponibile ad altri utenti).

e (i miei accentuazioni)

Non v'è alcun timeout in attesa di acks. Di solito questo non è un problema dal momento che i casi comuni di un ACK mancante - rete o il fallimento del cliente - si tradurrà nella connessione ottenere caduto (e quindi innescare il comportamento sopra descritto). Ancora, un timeout potrebbe essere utile per, ad esempio, trattare con vivo ma non risponde consumatori. Questo è già successo nella discussione . C'è un caso d'uso specifico che hai in mente che richiede tale funzionalità?

Il problema potrebbe anche essere che si verificano a causa di un modello client pull, è più difficile per il server di individuare una connessione interrotta (al contrario di un consumatore in vita, ma non risponde), in particolare per quanto il server sembra felice di aspettare per sempre per un asso.

Aggiornamento: Su Linux, è possibile collegare gestori di segnale per SIGTERM e/o SIGKILL e/o SIGINT e, auspicabilmente, chiudere la connessione in modo ordinato dal client. Su Windows, credo chiudendo da Task Manager richiama l'API Win32 TerminateProcess, di cui MSDN dice:

Se un processo è terminato da TerminateProcess, tutti i thread del processo saranno immediatamente terminate senza alcuna possibilità di correre codice aggiuntivo. Ciò significa che il thread non esegue codice di esecuzione nei blocchi del gestore di terminazione. Inoltre, nessuna DLL allegata viene informata che il processo è scollegamento.

Ciò significa che potrebbe essere difficile intercettazione e chiusura in modo ordinato.

Potrebbe valere la pena proseguire con l'elenco RabbitMQ con il proprio caso d'uso per un timeout dell'account.

+0

In base a tale mailing list, se l'utente interrompe la connessione, dovrebbe funzionare correttamente. Tuttavia, kill -9 o end process in taskmanager dovrebbe anche terminare la connessione in quel modo. Ma ancora non funziona correttamente. – Unknown

11

Non vedo amqp_consumer.py o amqp_producer.py nel tarball, quindi riprodurre l'errore è complicato.

RabbitMQ termina le connessioni, rilasciando i loro messaggi non riconosciuti per la riconsegna ad altri client, ogni volta che viene detto dal sistema operativo che un socket è stato chiuso. I tuoi sintomi sono molto strani, in quanto anche uno kill -9 dovrebbe causare la pulizia corretta del socket TCP.

Alcune persone hanno notato problemi con i socket che sopravvivono più a lungo di quanto dovrebbero quando sono in esecuzione con un firewall o un dispositivo NAT tra i client AMQP e il server. Potrebbe essere un problema qui, o stai facendo girare tutto su localhost? Inoltre, su quale sistema operativo stai eseguendo i vari componenti del sistema?

ETA: Dal tuo commento qui sotto, immagino che mentre stai eseguendo il server su Linux, potresti aver eseguito i client su Windows. Se questo è il caso, allora potrebbe essere che il driver TCP di Windows non sta chiudendo correttamente i socket, che è diverso dal comportamento di kill-9 su Unix. (In Unix, il kernel si chiuderà correttamente le connessioni TCP su qualsiasi processo uccisi.)

Se questo è il caso, allora il cattiva notizia è che RabbitMQ può rilasciare solo le risorse quando il socket viene chiuso, per cui se il cliente il sistema operativo non lo fa, non c'è niente che possa fare. Questo è lo stesso di quasi tutti gli altri servizi basati su TCP.

, tuttavia, AMQP supporta un'opzione "heartbeat" proprio per questi casi, in cui il fabric di rete non è affidabile. Potresti provare a abilitare i battiti del cuore. Quando sono abilitati, se il server non riceve traffico all'interno di un intervallo configurabile, decide che la connessione deve essere morta.

La notizia negativa , tuttavia, è che non credo che py-amqplib supporti heartbeat al momento. Vale la pena provare, però!

+0

Mi dispiace per quello. Il produttore e il consumatore sono qui http://blogs.digitar.com/jjww/code-samples/ – Unknown

+0

Sto eseguendo rabbitmq su un server linux remoto mentre sto facendo girare il produttore e il consumatore. Mi rendo conto che la presa potrebbe non essere stata chiusa in modo pulito, ma è esattamente ciò che voglio emulare. Stavo testando per vedere come rabbitmq gestisce i processi in crash che potrebbero non aver chiuso il socket in modo pulito, e sfortunatamente non sembra gestirlo molto bene. – Unknown

+1

@Tony; come si abilita l'opzione "heartbeat" all'interno del server RabbitMQ (all'interno di /etc/rabbitmq/rabbitmq.config per esempio)? –

Problemi correlati