BLUF — Die Message-TTL von RabbitMQ begrenzt den Aufenthalt in einer Queue, nicht die Lebensdauer bereits zugestellter Arbeit. Übergeben Sie eine unveränderliche fachliche Ablaufzeit im Auftrag, prüfen Sie diese unmittelbar vor dem Modellaufruf erneut und erfassen Sie „abgelaufen, nicht gestartet“ getrennt von Ausführungsfehlern. Ein kleineres Prefetch-Limit reduziert lokales Warten, ersetzt aber keine Zulassungsprüfung. Eine Dead-Letter-Zustellung erlaubt keinen Neustart der Frist.
Betrachten Sie einen rein lesenden Auftrag zur Zusammenfassung eines Vorfalls. Er ist nur nützlich, solange ein Operator den aktuellen Alarm untersucht. Der Consumer erhält ihn rechtzeitig, wartet aber auf einen freien Inferenzplatz. Bis dieser verfügbar ist, ist der Kontext überholt. Der Broker hat korrekt zugestellt; die Anwendung würde trotzdem falsch handeln, wenn sie jetzt startet. Dieser Beitrag untersucht genau die Grenze zwischen Zustellung und Ausführung. Das übergeordnete Retry-Budget begrenzt Wiederholungsversuche, beantwortet aber nicht, ob ein vorab zugestellter Auftrag noch nützlich ist.
Vier unterschiedliche Zeitgrenzen
Die TTL-Dokumentation von RabbitMQ definiert Message-TTL als Aufbewahrungsdauer in einer Queue. Sie beschreibt auch ein Zustellungsrennen: Eine Nachricht kann nach dem Schreiben in den Socket und vor dem Empfang beim Consumer ablaufen. Zusätzlich kann ein bereits zugestellter Auftrag im Anwendungspuffer warten. Weder die Queue-Tiefe noch eine erfolgreiche Zustellung beweisen einen gestarteten Modellaufruf.
Die Eigenschaft expiration enthält eine Dauer in Millisekunden als Zeichenkette. Wenn nachrichtenspezifische TTL und Message-TTL der Queue gleichzeitig gelten, entscheidet der kleinere Wert. Dagegen betrifft x-expires die Löschung einer ungenutzten Queue. Das ist keine Auftragsfrist; bei dieser Queue-Löschung werden ihre Nachrichten nicht als Dead Letters weitergeleitet. Ein Ausführungstimeout ist wiederum ein anderer Mechanismus: Er betrifft gestartete Arbeit und benötigt einen geprüften Abbruchvertrag.
| Kontrolle | Grenze | Beweist nicht |
|---|---|---|
| Message-TTL | Aufenthalt in Broker-Queue | Rechtzeitigen Start nach Zustellung |
| Queue-Ablauf: x-expires | Lebensdauer ungenutzter Queue | Abbruch einzelner Aufträge |
| Fachliche Frist | Nützlichkeit über mehrere Stationen | Gestopptes Backend |
| Ausführungstimeout | Bereits gestartete Operation | Erfolgreichen entfernten Abbruch |
Verwenden Sie keinen prozesslokalen monotonen Zeitstempel als übertragbare fachliche Frist. Speichern Sie eine absolute Ablaufzeit mit einer ausdrücklichen Regel für Zeitsynchronisation und Unsicherheit. Für lokal verstrichene Zeit eignet sich die monotone Uhr. Die fachliche Frist muss bei erneuter Zustellung, Wiederholung, Dead-Letter-Verarbeitung und Neustart unverändert bleiben.
Was der ausgeführte Broker-Test gezeigt hat
Der lokale Test verwendete RabbitMQ 4.0.5 aus dem Ubuntu-Paket 4.0.5-10ubuntu5.2, Erlang/OTP 27.3.4.6 und Pika 1.3.2. Das sind Reproduktionsstände, keine Empfehlung für eine aktuelle Produktivversion. Ein echter isolierter Loopback-Broker verarbeitete klassische Queues mit Publisher Confirms und manuellen Bestätigungen. Die Aufträge waren synthetisch und rein lesend; kein Modellanbieter wurde aufgerufen. Das Brokerverhalten wurde nicht durch einen Mock ersetzt.
Jeder Auftrag erhielt eine Message-TTL von 600 ms und expires_at_ms als unveränderlichen Wert im JSON-Body. Im Queue-Fall wartete der Test vor dem Abruf eine Sekunde. Die Prefetch-Fälle veröffentlichten jeweils drei Aufträge, empfingen bis zum eingestellten Limit, warteten 250 ms im Event-Loop und anschließend weitere 800 ms bis zur Startprüfung. Diese kurzen Testzeiten machen die Grenze sichtbar; sie sind weder Produktionsempfehlungen noch Durchsatzmessungen.
| Testfall | Beobachtung | Anwendungsentscheidung |
|---|---|---|
| Queue-Aufenthalt über 600 ms | Dead Letter; expiration fehlt | Ursprüngliche alte Frist ablehnen |
| Prefetch 1; drei Aufträge | Einer zugestellt; zwei beim Broker abgelaufen | Einen lokalen Auftrag ablehnen |
| Prefetch 3; drei Aufträge | Drei vor Ablauf zugestellt | Alle drei nach Warten ablehnen |
| Requeue nach Ablauf | Ursprungsqueue leer; Dead Letter empfangen | Unveränderte Frist ablehnen |
Bei Prefetch eins wurde ein Auftrag zugestellt und unbestätigt gehalten. Die anderen beiden blieben beim Broker und waren bei der Prüfung nach Fristablauf nicht mehr abrufbar. Bei Prefetch drei wurden alle drei Aufträge rechtzeitig zugestellt und verblieben in der lokalen Warteliste, bis die Anwendung sie ablehnte. Alle vier zugestellten Aufträge erhielten den Zustand expired_not_started; kein Modellaufruf wurde gestartet. Das zeigt, dass Prefetch den Ort des Wartens verändert. Es quantifiziert keine Kosteneinsparung.
Der gesonderte Queue-Fall erreichte das Dead-Letter-Ziel mit dem Grund expired. Die Eigenschaft expiration fehlte, während die absolute Ablaufzeit im JSON-Body unverändert blieb. Ein weiterer Auftrag wurde abgerufen, über seine Frist hinaus gehalten und mit requeue=true negativ bestätigt. Er war danach nicht mehr aus seiner ursprünglichen Queue abrufbar und erreichte das Dead-Letter-Ziel mit unveränderter fachlicher Frist. Beide Dead-Letter-Verarbeiter lehnten die veraltete Arbeit ab. Für diese von der Anwendung beobachteten Fälle enthält das gespeicherte Ergebnisregister sechs expired_not_started-Einträge. Die zwei beim Broker abgelaufenen Aufträge des Prefetch-eins-Falls wurden nicht durch dieses Consumer-Register erfasst; es ist daher kein vollständiger Ende-zu-Ende-Nachweis.
Ablauf: Zustellung ist noch kein Start
IN DER QUEUE → ZUGESTELLT, UNBESTÄTIGT → LOKALES WARTEN → FRISTPRÜFUNG → MODELLAUFRUF. Die Broker-TTL betrifft den Queue-Aufenthalt. Die Startprüfung erfolgt nach lokalem Warten, einschließlich des Wartens auf einen Parallelitätsplatz. Ist die Frist vorbei, folgt der terminale Ablaufpfad statt des Modellaufrufs. Halten Sie Empfangszeit, Prüfzeit und ursprüngliche Ablaufzeit als getrennte Trace-Felder fest.
Im Prefetch-drei-Test liefen alle drei Empfangs-Callbacks vor der 600-ms-Frist. Die Startprüfungen erfolgten erst nach dem bewusst verzögerten lokalen Warten. Der Broker holte die bereits zugestellten Bodies nicht zurück. Eine ausschließlich im Empfangs-Callback ausgeführte Prüfung hätte den späteren Ablauf verpasst. Wenn Adapter oder SDK weitere Warteschlangen einführen, entsteht eine zusätzliche Prüfgrenze.
Die letzte verantwortbare Zulassungsprüfung
Vergeben Sie bei Veröffentlichung eine stabile Auftrags-ID, unveränderliches expires_at_ms und eine Schemaversion. Behandeln Sie fehlende, ungültige oder unplausibel weit entfernte Fristen nach einer festgelegten Regel. Berechnen Sie die Broker-TTL aus dem Restbudget, statt bei jeder Neuveröffentlichung die ursprüngliche Gesamtdauer erneut zu gewähren. Bereits abgelaufene Aufträge gehören vor der Veröffentlichung abgelehnt. Validieren Sie den Auftrag an einem vertrauenswürdigen Eingang, damit ein nicht vertrauenswürdiger Produzent seine Befugnisse nicht selbst verlängert.
Prüfen Sie beim Empfang das Datenformat und registrieren Sie den Auftrag als zugestellt, aber nicht gestartet. Begrenzen Sie Prefetch und lokalen Puffer. Warten Sie gemäß Ihrer Kapazitätsregel auf einen Ausführungsplatz. Berechnen Sie unmittelbar vor dem Start: Rest = expires_at_ms − Worker-Uhrzeit_ms − Zeitunsicherheit_ms. Lehnen Sie ab, wenn der Rest nicht positiv ist. Benötigt Ihr Vertrag ein Mindestfenster für sinnvolle Ausführung, reservieren Sie auch dieses und den Abschlussaufwand. Der Test prüft Fristablauf, keine Vorhersage der Fertigstellungszeit.
Die Unsicherheitsmarge von 100 ms ist hier eine illustrative Regel, keine gemessene Uhrengrenze. Ein kontrollierter Rechenfall verwendet Worker-Zeit 10.000 ms und Frist 10.080 ms: Ohne Marge wäre eine Zulassung möglich, mit 100 ms Marge wird abgelehnt. Im Betrieb müssen Sie die tatsächliche Unsicherheit zwischen Produzent und Worker bestimmen und überwachen. Bei unbekanntem Synchronisationszustand beweist eine vermeintlich konservative Konstante nichts. Stoppen Sie die Zulassung oder wechseln Sie in einen ausdrücklich definierten eingeschränkten Modus.
Leiten Sie nach Zulassung einen lokalen Timeout aus dem Restbudget ab. Eine erfolgreiche Prüfung garantiert weder rechtzeitige Fertigstellung noch einen verzögerungsfreien Netzwerkaufruf. Platzieren Sie die Prüfung möglichst nahe an der tatsächlichen Ausführung, geben Sie die Frist weiter und testen Sie das Abbruchverhalten des Backends. Kontrolliertes Herunterfahren erklärt, warum das Ende eines wartenden Tasks noch kein Ende der Backend-Arbeit beweist.
Bestätigung und terminale Zustände
| Zustand an der Grenze | Maßnahme | Restrisiko |
|---|---|---|
| Vor Start abgelaufen | Terminalen Ablauf speichern; bestätigen | Absturz zwischen Speicher und Ack |
| Abgelaufen; Quarantäne nötig | Ohne Requeue an konfiguriertes DLX ablehnen | Standard-DLX kann verlieren |
| Noch nützlich; Kapazität frei | Erneut prüfen; Timeout aus Restbudget | Ablauf während Ausführung |
| Zeitunsicherheit unbegrenzt | Stoppen oder definierten Ersatzmodus nutzen | Verfügbarkeit sinkt |
| Gestartet; Frist überschritten | Abbruch anfordern; Ergebnis weiter verfolgen | Entfernte Arbeit kann weiterlaufen |
Für veraltete Arbeit können Sie einen terminalen Zustand expired_not_started speichern und bestätigen oder ohne Requeue an einen bewusst konfigurierten Quarantänepfad ablehnen. Keine dieser Varianten liefert automatisch zuverlässige Auditdaten. Speichern vor Bestätigung kann nach einem Absturz erneute Zustellung verursachen. Bestätigung vor Speicherung kann den einzigen Ergebnisnachweis verlieren. Nutzen Sie einen idempotenten Ergebnisspeicher mit stabiler Auftrags-ID, wiederholungssichere Consumer und einen Abgleich fehlender Ergebnisse. Das lokale Testregister ist kein transaktionales Outbox-System und kein Nachweis von Absturzfestigkeit.
Vermeiden Sie endloses Requeue bereits abgelaufener Arbeit. Laut Dead-Letter-Dokumentation wird die ursprüngliche TTL bei der Weiterleitung entfernt. Die Dokumentation warnt außerdem: Standardmäßiges Dead-Letter-Republishing verwendet intern keine Publisher Confirms und kann Nachrichten verlieren, wenn das Ziel sie nicht annehmen kann. Quorum-Queues unterstützen einen gesondert konfigurierten At-least-once-Modus. Dieser Test mit klassischen Queues validiert ihn nicht. Bevorzugen Sie im Betrieb Policies gegenüber fest kodierten Queue-Argumenten; der wegwerfbare Test verwendet Argumente nur zur Isolation seiner Topologie.
Prefetch bleibt ein Kapazitätskompromiss
Die Consumer-Prefetch-Dokumentation erläutert, dass ein nicht globales Limit pro Consumer gilt; null bedeutet unbegrenzt. Zusätzliche Consumer verändern daher die Gesamtzahl zugestellter, unbestätigter Nachrichten. Kleine Limits reduzieren lokales Warten, können aber Durchsatz kosten, wenn Zustelllatenz Worker leer laufen lässt. Große Limits können Rückstau in Consumern verstecken, obwohl der Ready-Zähler des Brokers beruhigend aussieht.
Messen Sie bereitstehende, unbestätigte und lokal wartende Arbeit getrennt. Erfassen Sie Queue- und Consumer-Aufenthalt. Unterscheiden Sie Ablauf vor Empfang, Ablauf vor Start, Ausführungsfehler, Fertigstellung und unbekannten Ausgang. Auftrags-IDs gehören nicht in Metrik-Labels, sondern in geschützte Traces oder den Ergebnisspeicher. Telemetry-Backpressure bleibt ein eigenständiges Transportproblem für Nachweise: Ein verlorener Monitoring-Eintrag beweist nicht, dass kein Auftrag gestartet wurde.
Freigabecheckliste und nächster Schritt
1. Reproduzieren Sie Queue-Ablauf, lokales Warten nach Zustellung, Requeue und Dead-Letter-Verarbeitung mit den Broker- und Clientständen Ihrer Bereitstellung.
2. Testen Sie Prefetch und Worker-Parallelität unter realistischem Rückstau. Der instrumentierte Dispatch muss für abgelaufene Aufträge null Aufrufe zeigen; eine fehlende Erfolgsantwort reicht nicht.
3. Injizieren Sie Uhrabweichungen, ungültige Fristen, Ausfall des Ergebnisspeichers und Worker-Neustart. Bewahren Sie die ursprüngliche Ablaufzeit, vermeiden Sie endloses Requeue und benennen Sie unbekannte Ergebnisse.
4. Prüfen Sie echte Modelltimeouts separat, einschließlich Arbeit, die nach Abbruch weiterläuft. Erfassen Sie solche Arbeit nicht als „abgelaufen, nicht gestartet“.
5. Definieren Sie Verantwortlichkeit und Aufbewahrung terminaler Ergebnisse. Broker-Ablauf ohne Dead-Letter-Beobachter kann ohne Anwendungsempfang bleiben. Wenn vollständige Bilanzierung erforderlich ist, gleichen Sie mit dem Bestand akzeptierter Aufträge beim Produzenten ab.
Bringen Sie für eine KI-Betriebsprüfung eine Queue-Topologie, deren Prefetch- und Parallelitätseinstellungen sowie ein Beispiel veralteter Arbeit mit. Das verwertbare Ergebnis ist eine ausführbare Fristprüfung mit Ergebnisregister und klaren Verlustgrenzen – nicht eine weitere TTL-Einstellung, die nur scheinbar den gesamten Ablauf abdeckt.


