2009-08-28 3 views
17

Ich probiere RabbitMQ mit this Python Bindung aus.Wie wird die Timeout-Erkennung auf einem RabbitMQ-Server festgelegt?

Eine Sache, die ich bemerkte, ist, dass, wenn ich einen Verbraucher unrein töte (emuliert ein abgestürztes Programm), der Server denkt, dass dieser Verbraucher noch dort für eine lange Zeit ist. Das hat zur Folge, dass jede zweite Nachricht ignoriert wird.

Zum Beispiel, wenn Sie einen Verbraucher 1 Mal töten und erneut verbinden, dann werden 1/2 Nachrichten ignoriert. Wenn Sie einen anderen Kunden töten, werden 2/3 Nachrichten ignoriert. Wenn Sie eine 3. töten, werden 3/4 Nachrichten ignoriert und so weiter.

Ich habe versucht, Bestätigungen zu aktivieren, aber es scheint nicht zu helfen. Die einzige Lösung, die ich gefunden habe, ist, den Server manuell zu stoppen und ihn zurückzusetzen.

Gibt es einen besseren Weg?

wie dieses Szenario

  • Run rabbitmq neu erstellen.

  • Unarchiv this library.

  • Laden Sie den Verbraucher und den Herausgeber here herunter. Führen Sie amqp_consumer.py zweimal aus. Führen Sie amqp_publisher.py aus, geben Sie einige Daten ein und beobachten Sie, dass es wie erwartet funktioniert. Nachrichten werden im Round-Robin-Stil empfangen.

  • Töten Sie einen der Verbraucherprozesse mit kill -9 oder Task-Manager.

  • Wenn Sie jetzt eine Nachricht veröffentlichen, gehen 50% der Nachrichten verloren.

+0

Ich aktualisierte meine Antwort. –

+0

Ich kann das nicht reproduzieren. Welche Version von Linux verwenden Sie? –

+3

Gute Frage - dies ist ein kritisches Problem, wenn hinter einer Firewall oder IP Load-Balancing-Appliance ausgeführt wird, die leere Sockets nach N Sekunden löscht, weil weder RabbitMQ noch der Client jemals informiert werden, dass der Socket gegangen ist weg, bis sie es versuchen. –

Antwort

2

Bitte geben Sie noch ein paar Besonderheiten in Bezug auf die Komponenten, die Sie deklariert haben. Üblicherweise (und unabhängig von der der Client-Implementierung) eine Warteschlange mit den Eigenschaften

  • exklusiv und
  • Auto löschen

sollte, sobald die Verbindung zwischen dem erklärt Client und dem Broker entfernt erhalten bricht zusammen. Dies wird Ihnen jedoch nicht mit gemeinsam genutzten Warteschlangen helfen. Bitte erläutern Sie etwas, was genau Sie versuchen zu modellieren.

+0

Ich spreche nicht darüber, wann Warteschlangen gelöscht werden. Ich spreche darüber, wie Rabbitmq für eine sehr lange Zeit nicht abgestürzte Verbindungen entdeckt und versucht, ihnen Nachrichten zu senden, als ob sie immer noch da sind. – Unknown

5

RabbitMQ hat keine Zeitüberschreitung bei Bestätigungen vom Client, dass eine Nachricht verarbeitet wurde: siehe this post (der gesamte Thread könnte von Interesse sein). Einige hervorstechende Punkte aus dem Post:

Die AMQP Ack-Modell für Abonnements und "Pull" sind identisch. In beiden Fällen wird die Nachricht auf dem Server gespeichert, aber ist nicht verfügbar für andere Verbraucher, bis es entweder bestätigt wurde (und wird entfernt), nack'ed (mit Basic.ablehnen; obwohl RabbitMQ dies nicht implementiert) oder der Kanal/Verbindung ist geschlossen (bei dieser Punkt wird die Nachricht verfügbar an andere Verbraucher).

und (meine Hervorhebungen)

Es gibt kein Timeout für acks auf der Warteliste. Normalerweise ist das kein Problem da die häufigsten Fälle eines fehlenden ack - Netzwerk oder Client-Ausfall - in der Verbindung führen immer fiel (und damit lösen die Verhalten wie oben beschrieben). Immer noch ein Timeout könnte nützlich sein, sagen wir Deal mit lebendig, aber nicht mehr reagiert Verbraucher. Das ist in Diskussion zuvor aufgetreten. Gibt es einen bestimmten Anwendungsfall, den Sie im Sinn haben, dass eine solche Funktionalität erfordert?

Das Problem, weil in einem Client-Pull-Modell könnte auch auftreten, ist es schwieriger ist, dass der Server eine unterbrochene Verbindung zu erkennen (im Gegensatz zu einem lebendig, aber nicht reagiert der Verbraucher gegenüber), insbesondere da der Server ewig zu warten glücklich scheint ein Ack.

Update: Unter Linux können Sie Signalhandler für SIGTERM und/oder SIGKILL und/oder SIGINT anhängen und hoffentlich die Verbindung in geordneter Weise vom Client schließen. Unter Windows, ich glaube von Task-Manager zu schließen ruft die Win32 TerminateProcess API, über die MSDN sagt:

Wenn ein Prozess, durch TerminateProcess beendet ist, werden alle Fäden des Prozess sofort ohne Chance beendet werden laufen zusätzlicher Code. Dies bedeutet, dass der Thread Code in Terminierungshandler Blöcke nicht ausführt. Außerdem werden keine angehängten DLLs benachrichtigt, dass der Prozess löst.

Dies bedeutet, dass es schwierig sein kann, den Abschluss zu finden und ordnungsgemäß zu schließen.

Es könnte sich lohnen, in der RabbitMQ-Liste mit Ihrem eigenen Anwendungsfall nach einem ack-Timeout zu suchen.

+0

Laut dieser Mailing-Liste, wenn der Verbraucher die Verbindung beendet, sollte es korrekt funktionieren. Kill -9 oder End-Prozess im Taskmanager sollte jedoch auch die Verbindung auf diese Weise beenden. Aber es funktioniert immer noch nicht richtig. – Unknown

11

Ich sehe nicht amqp_consumer.py oder amqp_producer.py in der Tarball, so die Wiedergabe der Fehler ist schwierig.

RabbitMQ beendet Verbindungen und gibt ihre nicht bestätigten Nachrichten für die erneute Zustellung an andere Clients frei, sobald das Betriebssystem meldet, dass ein Socket geschlossen wurde. Ihre Symptome sind sehr merkwürdig, da sogar ein kill -9 dazu führen sollte, dass der TCP-Socket ordnungsgemäß bereinigt wird.

Einige Leute haben festgestellt, dass Probleme mit Sockets länger überleben als sie sollten, wenn sie mit einer Firewall oder einem NAT-Gerät zwischen den AMQP-Clients und dem Server laufen. Könnte das ein Problem sein, oder läufst du alles auf localhost? Auf welchem ​​Betriebssystem laufen die verschiedenen Komponenten des Systems?

ETA: Von Ihrem Kommentar unten vermute ich, dass Sie die Clients unter Windows ausführen, während Sie den Server unter Linux ausführen. Wenn dies der Fall ist, könnte es sein, dass der Windows TCP-Treiber die Sockets nicht korrekt schließt, was sich von dem Kill-9-Verhalten unter Unix unterscheidet. (Unter Unix wird der Kernel richtig die TCP-Verbindungen auf jedem getöteten Prozess schließen.)

Wenn das der Fall ist, dann ist die schlechte Nachricht ist, dass RabbitMQ kann nur Ressourcen freigeben, wenn der Socket geschlossen ist, so dass, wenn der Kunde Betriebssystem tut das nicht, es gibt nichts, was es tun kann. Dies ist der gleiche wie bei fast jedem anderen TCP-basierten Dienst.

Die gute Nachrichten, obwohl, dass AMQP eine "Herzschlag" -Option für genau diese Fälle unterstützt, wo die Netzwerkstruktur nicht vertrauenswürdig ist. Sie könnten versuchen, Heartbeats zu aktivieren. Wenn der Server nach der Aktivierung keinen Datenverkehr innerhalb eines konfigurierbaren Intervalls empfängt, entscheidet er, dass die Verbindung inaktiv sein muss.

Die schlechte Nachrichten ist jedoch, dass ich glaube nicht, py-amqplib unterstützt Herzschläge im Moment. Einen Versuch wert, obwohl!

+0

Entschuldigung. Der Produzent und Verbraucher ist hier http://blogs.digitar.com/jjww/code-samples/ – Unknown

+0

Ich rase rabbitmq auf einem Remote-Linux-Server, während ich den Hersteller und Verbraucher laufen. Ich stelle fest, dass der Socket möglicherweise nicht sauber geschlossen wurde, aber das ist genau das, was ich emulieren möchte. Ich habe getestet, wie rabbitmq abgestürzte Prozesse handhabt, die den Sockel nicht sauber geschlossen haben, und leider scheint das nicht so gut zu funktionieren. – Unknown

+1

@ Tony; Wie aktiviert man die "Heartbeat" Option innerhalb des RabbitMQ Servers (zB in /etc/rabbitmq/rabbitmq.config)? –

Verwandte Themen