Fehlerbehebung bei langsamer Nachrichtenverarbeitung: Identifizierung von RabbitMQ-Engpässen

Diagnostizieren Sie RabbitMQ-Verlangsamungen, indem Sie Engpässe bei Produzenten, Brokern, Warteschlangen, Verbrauchern, Festplatten und Bestätigungen trennen.

Fehlerbehebung bei langsamer Nachrichtenverarbeitung: Identifizierung von RabbitMQ-Engpässen

Wenn eine RabbitMQ-Warteschlange sich staut, zeigt die Warteschlange nur das Symptom. Der Engpass könnte ein langsamer Verbraucher, ein blockierter Herausgeber, ein Festplattenalarm, ein schlechter Prefetch-Wert, eine riesige Nachrichtenlast oder eine nachgelagerte Datenbank sein, die leise anfängt, Zeitüberschreitungen zu verursachen. Ein Neustart von RabbitMQ kann die Grafik für ein paar Minuten bereinigen, aber es behebt selten den Grund, warum Nachrichten langsam waren.

Der schnellste Weg zur Fehlerbehebung besteht darin, den Fluss in Teile zu zerlegen: Veröffentlichung in RabbitMQ, Weiterleitung an Warteschlangen, Speichern von Nachrichten, Zustellung an Verbraucher, Verarbeitung der Arbeit und Bestätigung des Abschlusses. Jedes Teil hinterlässt unterschiedliche Beweise.

Erste Aufteilung: bereit oder nicht bestätigt

Beginnen Sie mit den Warteschlangenzählern:

rabbitmqctl list_queues name messages_ready messages_unacknowledged consumers state

messages_ready bedeutet, dass Nachrichten in der Warteschlange sitzen und auf die Zustellung warten. Wenn diese Zahl wächst, hat RabbitMQ entweder keine verfügbaren Verbraucher, Verbraucher haben ihr Prefetch-Limit erreicht oder die Zustellung wird durch eine andere Bedingung blockiert.

messages_unacknowledged bedeutet, dass Nachrichten bereits an Verbraucher zugestellt wurden und RabbitMQ auf eine Bestätigung (ack), Nichtbestätigung (nack), Ablehnung (reject) oder Schließung des Kanals wartet. Wenn diese Zahl wächst, liegt der Engpass normalerweise im Verbraucher oder in etwas, das der Verbraucher aufruft.

Diese Unterscheidung ist wichtig. Wenn bereite Nachrichten hoch und nicht bestätigte niedrig sind, wird das Hinzufügen von mehr Broker-Speicher keine Verbraucher erscheinen lassen. Wenn nicht bestätigte Nachrichten hoch sind, kann das Hinzufügen weiterer Warteschlangenpartitionen möglicherweise nicht helfen, da die Arbeit die Warteschlange bereits verlassen hat.

Überprüfen, ob Verbraucher tatsächlich vorhanden sind

Eine überraschende Anzahl von „RabbitMQ ist langsam“-Vorfällen sind eigentlich „die Verbraucher laufen nicht“-Vorfälle. Die Bereitstellung ist fehlgeschlagen, die automatische Skalierung ging auf Null, Anmeldeinformationen wurden geändert, der falsche virtuelle Host wurde verwendet oder der Dienst ist mit der Staging-Umgebung verbunden, während Herausgeber in die Produktion veröffentlichen.

Verwenden Sie:

rabbitmqctl list_consumers queue_name channel_pid consumer_tag ack_required prefetch_count active

Wenn es keine Verbraucher gibt, beheben Sie das zuerst. Wenn Verbraucher vorhanden, aber inaktiv sind, überprüfen Sie die Anwendungsprotokolle und den Verbindungsstatus. Wenn jeder Verbraucher einen Prefetch von 1 hat und jede Nachricht mehrere Sekunden dauert, ist eine niedrige Zustellungskonkurrenz zu erwarten. Wenn jeder Verbraucher einen Prefetch von 500 hat und nicht bestätigte Nachrichten riesig sind, horten die Verbraucher möglicherweise Arbeit, die sie nicht schnell erledigen können.

Messen Sie die Verarbeitungszeit des Verbrauchers

RabbitMQ kann Ihnen sagen, dass Nachrichten nicht bestätigt sind. Es kann Ihnen nicht sagen, ob der Verbraucher eine riesige Nutzlast parst, auf PostgreSQL wartet, einen HTTP-Aufruf wiederholt oder an einer Sperre hängt.

Fügen Sie Timing um den eigentlichen Handler hinzu:

message_received_at
decode_ms
business_logic_ms
database_ms
external_api_ms
ack_ms
message_completed_at

Sie brauchen kein perfektes Tracing-System, um etwas zu lernen. Selbst ein paar strukturierte Protokollfelder können zeigen, dass der Handler normalerweise 80 ms braucht, aber jetzt 4 Sekunden auf eine nachgelagerte API wartet.

Wenn die Arbeit langsam, aber parallelisierbar ist, fügen Sie Verbraucherinstanzen hinzu oder erhöhen Sie die interne Worker-Konkurrenz. Wenn das nachgelagerte System die Grenze ist, kann das Hinzufügen von Verbrauchern die Sache verschlimmern. Möglicherweise benötigen Sie Ratenbegrenzung, Batch-Verarbeitung, Caching oder eine separate Wiederholungswarteschlange.

Passen Sie Prefetch an, nachdem Sie den Handler verstanden haben

Prefetch steuert, wie viele nicht bestätigte Nachrichten RabbitMQ an jeden Verbraucher senden kann. Es ist oft an Vorfällen mit langsamer Verarbeitung beteiligt, weil es ändert, wo der Rückstau sichtbar ist.

Bei niedrigem Prefetch bleiben Nachrichten in RabbitMQ bereit, bis ein Verbraucher für mehr bereit ist. Dies ist fair und leicht zu beobachten, kann aber sehr schnelle Verbraucher unterauslasten.

Bei hohem Prefetch bewegen sich Nachrichten schnell in die Verbraucher. Dies kann den Durchsatz für schnelle Handler verbessern, kann aber auch die Latenz verbergen. Ein langsamer Verbraucher mit einem großen Prefetch-Wert kann auf Hunderten von Nachrichten sitzen, während anderen Verbrauchern die Arbeit ausgeht.

Ein praktischer Schritt bei Vorfällen ist es, den Prefetch für langsame oder instabile Verbraucher zu senken und zu beobachten, ob sich die End-to-End-Latenz verbessert. Für schnelle Verbraucher mit niedriger CPU-Auslastung und hohen Bereit-Zählern erhöhen Sie vorsichtig den Prefetch und messen Sie erneut.

Suchen Sie nach Engpässen auf der Herausgeberseite

Manchmal staut sich die Warteschlange nicht, weil Verbraucher langsam sind. Sie staut sich, weil Herausgeber in Bursts veröffentlichen und dann ineffizient auf Bestätigungen warten.

Herausgeberbestätigungen sind das richtige Werkzeug, wenn Herausgeber wissen müssen, dass RabbitMQ Nachrichten akzeptiert hat. Das langsame Muster besteht darin, auf jede Bestätigung zu warten, bevor die nächste Nachricht veröffentlicht wird. Das macht jede Veröffentlichung zu einem Roundtrip.

Bessere Muster verwenden asynchrone Bestätigungen oder begrenzte Batches. Der Herausgeber kann eine begrenzte Anzahl von Nachrichten in der Schwebe halten, Nichtbestätigungen behandeln und dennoch vermeiden, bei jeder einzelnen Nachricht zu blockieren. Die Grenze ist wichtig. Unbegrenztes Veröffentlichen in der Schwebe kann den Engpass in den Herausgeberspeicher oder den Broker-Druck verlagern.

Überprüfen Sie die Metriken des Herausgebers: Veröffentlichungsrate, Bestätigungslatenz, Anzahl der Bestätigungen in der Schwebe, Wiederverbindungen, zurückgegebene Nachrichten und Kanalausnahmen. Vergleichen Sie in der Verwaltungsoberfläche die Veröffentlichungsraten mit den Zustellungs-/Bestätigungsraten. Wenn die Veröffentlichungsrate niedrig ist, obwohl die Anwendung beschäftigt ist, wartet der Produzent möglicherweise auf Bestätigungen, Transaktionen oder Verbindungswechsel.

Vermeiden Sie AMQP-Transaktionen für das Veröffentlichen mit hohem Durchsatz, es sei denn, es gibt einen bestimmten Grund. Sie sind für typisches zuverlässiges Veröffentlichen viel teurer als Herausgeberbestätigungen.

Überprüfen Sie die Festplatte, bevor Sie RabbitMQ die Schuld geben

Beständige Nachrichten, Quorum-Warteschlangen, Streams und große Rückstände betreffen alle die Festplatte. Wenn die Festplattenlatenz steigt, kann der Nachrichtenfluss drastisch langsamer werden.

Überprüfen Sie auf dem RabbitMQ-Knoten:

rabbitmq-diagnostics status
rabbitmq-diagnostics alarms
rabbitmq-diagnostics memory_breakdown

Auf Betriebssystemebene verwenden Sie Werkzeuge wie iostat, vmstat oder Ihre Cloud-Überwachungsdiagramme. Achten Sie auf Festplattenlatenz und E/A-Wartezeit, nicht nur auf den Durchsatz. Eine Cloud-Festplatte, die ihre Burst-Guthaben aufgebraucht hat, kann in der Konfiguration normal aussehen und in der Praxis schrecklich sein.

Wenn die Festplatte der Engpass ist, umfassen mögliche Korrekturen schnellere Speicherung, weniger beständige Schreibvorgänge, kleinere Nachrichten, bessere Bündelung von Herausgeberbestätigungen, Aufteilung von Warteschlangen oder das Verschieben von Wiederholungs-Workloads zu Streams oder einem anderen protokollorientierten System. Deaktivieren Sie nicht die Beständigkeit für Nachrichten, die das Geschäft nicht verlieren kann, nur um ein Diagramm grün zu machen.

Überprüfen Sie Alarme und blockierte Verbindungen

RabbitMQ schützt sich selbst mit Speicher- und Festplattenalarmen. Wenn ein Alarm aktiv ist, können Herausgeber blockiert werden. Dies kann von der Produzentenseite wie Anwendungsverlangsamung aussehen.

Führen Sie aus:

rabbitmq-diagnostics alarms
rabbitmqctl list_connections name user state channels send_pend recv_cnt send_cnt

Wenn Speicheralarme aktiv sind, finden Sie heraus, ob der Speicher von Warteschlangen, Verbindungen, nicht bestätigten Nachrichten, Binärdateien oder Plugins belegt wird. Wenn Festplattenalarme aktiv sind, schaffen Sie Speicherplatz oder fügen Sie Kapazität hinzu, bevor Sie versuchen, mehr Nachrichten durch den Broker zu drücken.

Blockierte Verbindungen sind an sich kein Fehler. Sie sind RabbitMQs Art, Herausgebern zu sagen, sie sollen langsamer machen, weil der Knoten die Verfügbarkeit schützt.

Nachrichtengröße kann der stille Übeltäter sein

Ein System, das 10.000 winzige Nachrichten pro Sekunde verarbeitet, kann mit 500 großen Nachrichten pro Sekunde kämpfen. Große Nutzlasten erhöhen die Netzwerkübertragung, den Speicherdruck, die Festplattenschreibvorgänge, die Garbage-Collection-Arbeit und die Verarbeitungszeit des Verbrauchers.

Wenn Nachrichten große Dokumente, Bilder, Berichte oder große Arrays enthalten, sollten Sie die Nutzlast in einem Objektspeicher oder einer Datenbank speichern und einen Verweis durch RabbitMQ senden. Fügen Sie genügend Metadaten für Routing und Idempotenz hinzu, aber halten Sie den Broker nach Möglichkeit aus der Rolle der Massenspeicherung heraus.

Überprüfen Sie auch die Komprimierungsoptionen. Das Komprimieren riesiger Nutzlasten kann die Netzwerk- und Festplattennutzung reduzieren, aber die CPU erhöhen. Ob das hilft, hängt davon ab, wo der Engpass liegt.

Wiederholungen können den Engpass erzeugen

Ein fehlschlagender nachgelagerter Dienst kann eine Nachricht in viele Versuche verwandeln. Wenn Verbraucher fehlgeschlagene Nachrichten sofort wieder in die Warteschlange stellen, verarbeiten sie möglicherweise wiederholt dieselben schlechten Nachrichten, während frische Arbeit wartet. Die Warteschlangentiefe kann steigen, die CPU kann beschäftigt aussehen, und es wird sehr wenig nützliche Arbeit erledigt.

Achten Sie auf hohe erneute Zustellungsraten und wiederholte Fehlerprotokolle mit denselben Nachrichten-IDs. Wenn dieselbe Nutzlast immer wieder fehlschlägt, verschieben Sie sie aus dem Hauptfluss. Ein Dead-Letter-Austausch, eine verzögerte Wiederholungswarteschlange oder ein geplanter Wiederholungsmechanismus gibt der Abhängigkeit Zeit, sich zu erholen, und hält Giftnachrichten davon ab, die normale Arbeit zu blockieren.

Seien Sie vorsichtig mit Wiederholungsstürmen. Wenn eine API für zehn Minuten ausfällt und jede Nachricht jede Sekunde wiederholt wird, wird die Erholung schwieriger, wenn die API zurückkommt. Verwenden Sie Backoff. Begrenzen Sie die Versuche. Machen Sie den endgültigen Fehler in einer Dead-Letter-Warteschlange mit genügend Kontext für die Untersuchung sichtbar.

Idempotenz ist auch Teil der Leistungsfehlerbehebung. Wenn ein Verbraucher nach teilweise abgeschlossener Arbeit wiederholt, können Duplikate Datenbankkonflikte, Eindeutigkeitsschlüsselfehler oder zusätzliche nachgelagerte Aufrufe erzeugen. Ein Handler, der dieselbe Nachricht sicher zweimal verarbeiten kann, ist viel einfacher zu skalieren und wiederherzustellen.

Raten in der Verwaltungsoberfläche benötigen Kontext

Die RabbitMQ-Verwaltungsoberfläche ist nützlich, aber Ratiendiagramme können irreführen, wenn Sie nur eine Linie lesen. Eine hohe Zustellrate bei einer niedrigen Bestätigungsrate bedeutet, dass Arbeit schneller ausgegeben wird, als sie abgeschlossen wird. Eine hohe Bestätigungsrate bei einer hohen Bereit-Zahl kann bedeuten, dass Verbraucher arbeiten, aber nicht genug, um aufzuholen. Eine niedrige Veröffentlichungsrate während eines Vorfalls kann bedeuten, dass Herausgeber blockiert sind oder auf Bestätigungen warten.

Betrachten Sie mehrere Raten zusammen:

  • publish: Nachrichten, die in Austausche eingehen.
  • deliver/get: Nachrichten, die an Verbraucher gesendet werden.
  • ack: Nachrichten, die von Verbrauchern abgeschlossen wurden.
  • redeliver: Nachrichten, die nach vorherigem Fehler oder Kanal-Schließung erneut zugestellt werden.

Für eine gesunde, stetige Arbeitswarteschlange sollten die Veröffentlichungs- und Bestätigungsraten im Laufe der Zeit nahe beieinander liegen. Kurze Bursts sind normal. Lange Lücken bedeuten, dass sich ein Rückstand ansammelt oder abgebaut wird. Wenn die erneuten Zustellungen stark ansteigen, fügen Sie nicht einfach mehr Verbraucher hinzu. Finden Sie heraus, warum Nachrichten zurückkommen.

Stichprobenfenster sind wichtig. Ein einminütiges Diagramm kann einen fünfsekündigen Stillstand verbergen, der Benutzer beeinträchtigt. Ein einsekündiges Diagramm kann normale Burstigkeit wie Chaos aussehen lassen. Passen Sie das Diagrammfenster an die Latenz an, die für Ihre Benutzer oder nachgelagerten Systeme wichtig ist.

Trennen Sie normalen Rückstand von defektem Rückstand

Nicht jeder Rückstand ist ein Notfall. Ein Batch-System kann absichtlich Arbeit während des Tages in die Warteschlange stellen und sie nachts abarbeiten. Ein benutzerorientierter Workflow kann ungesund sein, wenn Nachrichten dreißig Sekunden warten. Dieselbe Warteschlangentiefe kann in einem System akzeptabel und in einem anderen schwerwiegend sein.

Definieren Sie ein altersbasiertes Signal, nicht nur eine Anzahl. Die Nachrichtenanzahl sagt Ihnen, wie viele warten; das Nachrichtenalter sagt Ihnen, ob das Geschäft zurückfällt. Wenn Ihre Überwachung das älteste Nachrichtenalter oder die End-to-End-Zeit von der Veröffentlichung bis zur Bestätigung verfolgen kann, wird es Verlangsamungen früher erkennen als die Warteschlangentiefe allein.

Binden Sie Warnungen an diese Erwartung. Das Warnen bei 10.000 Nachrichten kann für eine nächtliche Exportwarteschlange laut sein und für eine Passwort-Zurücksetzungs-Warteschlange viel zu spät kommen. Das Warnen bei „älteste Nachricht älter als das Serviceziel“ ist normalerweise näher an dem, was Benutzer interessiert.

Eine heiße Warteschlange bleibt eine heiße Warteschlange

Das Hinzufügen von Cluster-Knoten teilt nicht automatisch eine Warteschlange auf alle Knoten auf. Eine einzelne heiße Warteschlange kann durch ihren Leader, ihre Verbraucher und ihren Speicherpfad begrenzt bleiben.

Wenn eine Warteschlange nicht zusammenhängende Arbeitstypen trägt, teilen Sie sie nach tatsächlichem Verarbeitungsverhalten auf. Zum Beispiel sollten Bildskalierung, E-Mail-Versand und Abrechnungserfassung nicht eine generische jobs-Warteschlange teilen, wenn sie unterschiedliche Latenz- und Wiederholungsanforderungen haben. Separate Warteschlangen ermöglichen es Ihnen, Verbraucher unabhängig zu skalieren und Giftnachrichten zu isolieren.

Wenn ein Arbeitstyp immer noch zu heiß ist, teilen Sie ihn nur auf, wenn die Ordnungsanforderungen dies zulassen. Das Aufteilen nach Kunden-ID, Mandant, Region oder einem anderen stabilen Schlüssel kann funktionieren, treibt aber die Komplexität in Routing und Betrieb. Teilen Sie nicht auf, nur um die Behebung eines langsamen Handlers zu vermeiden.

Eine ruhige Reihenfolge zur Fehlerbehebung

Bei einem Vorfall verwende ich diese Reihenfolge:

  1. Überprüfen Sie Alarme: Speicher, Festplatte und blockierte Verbindungen.
  2. Überprüfen Sie Warteschlangenzähler: bereit, nicht bestätigt, Verbraucher.
  3. Überprüfen Sie Verbraucherprotokolle und Handler-Timing.
  4. Überprüfen Sie Prefetch und nicht bestätigte Verteilung pro Verbraucher.
  5. Überprüfen Sie die Bestätigungslatenz des Herausgebers und zurückgegebene Nachrichten.
  6. Überprüfen Sie die Festplattenlatenz und den Knotenressourcendruck.
  7. Überprüfen Sie die Nachrichtengröße und kürzliche Nutzlaständerungen.
  8. Erst dann ändern Sie die Topologie oder fügen Broker-Knoten hinzu.

Diese Reihenfolge verhindert einen häufigen Fehler: Skalieren des Brokers, wenn der Engpass ein Worker ist, oder Skalieren von Workern, wenn der Engpass die Festplatte ist.

RabbitMQ ist normalerweise sehr klar, sobald Sie die richtigen Zähler lesen. Eine wachsende Bereit-Zahl sagt, dass Arbeit wartet. Eine wachsende nicht bestätigte Zahl sagt, dass Arbeit in Bearbeitung ist, aber nicht abgeschlossen wird. Ein blockierter Herausgeber sagt, dass der Broker sich selbst schützt. Behandeln Sie jedes Signal als Hinweis, und die Behebung wird viel weniger dramatisch.