17

Also das Szenario ist, dass ich eine SB-Warteschlange verwenden, um ausgehende Rückrufe zu anderen Diensten zu drosseln. Eines der Standardprobleme beim Zurückrufen zu anderen Diensten besteht darin, dass sie für unkontrollierbare Zeitspannen heruntergefahren sein können. Wenn ich feststelle, dass das Ziel nicht erreichbar ist/antwortet, welches ist das beste Muster, um diese Nachricht aufzugeben, so dass sie nicht sofort wieder in der Warteschlange erscheint?Was ist der richtige Weg, um eine Azure SB-Nachricht aufzugeben, damit sie in Zukunft auf eine Weise sichtbar wird, die ich kontrollieren kann?

sind hier einige Ansätze, die ich bin entweder bewusst, versucht haben, oder bin am überlegen:

  • Natürlich, wenn ich BrokeredMessage::Abandon() nur die Meldung freigeschaltet werden und in die Warteschlange stellen. Dies ist offensichtlich unerwünscht für dieses Szenario und was ich versuche zu vermeiden.

  • Wenn ich einfach die Tatsache ignoriere, dass ich in einen Fehler geriet und Abandon nie anrufe, wird es davon abhalten, sofort zu erscheinen, aber ich habe wirklich keine feinkörnige Kontrolle darüber, wie lange es wieder auftaucht und ich möchte eine verfallende Wiederholungsstrategie implementieren.

  • Ich dachte, vielleicht ich BrokeredMessage::Abandon(IDictionary<string, object>) nennen könnte und irgendwie die ScheduledEnqueueTimeUTC Eigenschaft aktualisieren, aber ich habe schon versucht, diese und es scheint nicht ein Weg, um diese Eigenschaft über die anfängliche Senden der Nachricht zu beeinflussen. Macht Sinn, ist aber einen Versuch wert.

  • habe ich als nur BrokeredMessage::Complete() in dieser Situation mit und eigentlich nur eine neue Kopie der Nachricht mit dem ScheduledEqueueTimeUTC Eigenschaftssatz Einreihen.

Die letzte Kugel scheint fast zu plump, aber ich komme zu dem Schluss, es ist wahrscheinlich die richtige Antwort der inhärente Natur von Warteschlangen gegeben. Ich habe mir gedacht, dass es eine schönere Möglichkeit gibt, dies in Azure SB-Warteschlangen zu tun, die ich vermisse.

Antwort

6

Wenn Sie eine Nachricht für eine Weile weg setzen wollen und Sie haben einen Ort, um die SequenceNumber aufzuschreiben (die in einer sitzungs Warteschlange in Sitzungsstatus sein kann), können Sie Aufschieben() es.Zurückgestellte Nachrichten können mithilfe einer speziellen Empfangsüberladung mit der Sequenznummer abgerufen werden. das ist auch der einzige Weg, um wieder an sie heranzukommen, außer dass sie auslaufen, so vorsichtig. Diese Funktion wurde für Workflows und State-Machines entwickelt, damit sie die Meldung von Out-of-Order-Nachrichten verarbeiten können.

+4

Ok, also, sagen Sie mir, ob das richtig klingt: Wir können die ursprüngliche Nachricht in der primären Warteschlange verzögern und eine "Wiederholungs" -Nachricht in die sekundäre Warteschlange stellen (wahrscheinlich mit ScheduledEnqueueTimeUTC), die dann die Sequenznummer der ursprünglichen Nachricht hat Den kann ich dann zurückgehen und über die spezielle Receive() Überladung greifen. –

+4

Sie können das tun. –

+0

Ich bin verwirrt, was die sekundäre Warteschlange fügt, die nicht durch Ihre "schwere Hand" -Lösung des Kopierens der Nachricht mit einer geplanten Lieferzeit erreicht wird. Das einzige Problem, das ich bei der Implementierung gesehen habe, ist, dass die Lieferzählung immer auf 1 zurückgesetzt wird, so dass es keine gute Quelle ist, um die Eingabe für die exponentielle Backoff-Berechnung zu bestimmen. –

0

Wenn ich Sie wäre, würde ich eine der vielen Seiten konsultieren, die im Internet für eine Lösung sind. Grundsätzlich möchten Sie eine Wiederholung haben, die, wenn sie fehlschlägt, die Nachricht nacheinander in eine Warteschlange für nicht zustellbare Nachrichten sendet. Diese Nachrichten können wir dann zu einem späteren Zeitpunkt erneut anfordern. Dies könnte manuell oder automatisiert sein, je nach Anforderungen.

Bitte beachten Sie, dass, während die Seite, die ich Ihnen gesendet habe, sich auf camel und daher Java bezieht, alles, was auf dieser Seite beschrieben wird, .NET und azure ist. Hier ist ein mehr. NET, wenn Sie interessiert sind http://www.eaipatterns.com/

+1

Alistair, vielen Dank für die Anregung. Ich werde die Links sicher überprüfen. Wir hatten gehofft, separate Warteschlangen/separate Verarbeitung für diese Situation zu vermeiden. Letztendlich haben wir die Nachrichten nach einer gewissen Anzahl von Verarbeitungsversuchen nicht mehr geschrieben, wir haben nur nach einer einfacheren Möglichkeit gesucht, die Wiederholungen zu verteilen, bis wir das Maximum erreicht haben. Am Ende würde ich denken, dass, wenn wir die Nachricht an die selbe Schlange mit einem neuen "ScheduledEnQueueTimeUTC" -Wert zurückschicken würden, uns wahrscheinlich kaufen würde, was wir im SB-Fall wollen. Ich hoffte nur, dass es eine sauberere Möglichkeit gab, dies in der API zu tun die Nachricht. –

1

In bullet # 2 oben: Können Sie nicht nur die TTL-Zeitspanne auf die Nachricht beim Aufruf Receive(TimeSpan) anstelle der Standard Receive()? Dann können Sie die Nachricht einfach abbrechen (ohne Abandon() aufzurufen), und die Nachricht sollte wieder in der Warteschlange angezeigt werden, wenn der TTL abläuft. Das gibt Ihnen nicht feinkörnige Kontrolle, um zu sagen, dass "nach x Sekunden wieder angezeigt wird" gibt es Ihnen Vorhersehbarkeit für, wenn die Nachricht erneut angezeigt wird.

Hinweis: Bei speicherbasierten Warteschlangen können Sie das Unsichtbarkeits-Zeitlimit aktualisieren, sodass Ihnen eine feinkörnige Steuerung für das erneute Auftreten von Nachrichten bietet.

+1

David, danke für den Vorschlag. Das Problem dabei ist, dass wir eine intelligente, verfallende Wiederholung verwenden wollen. Also, für ein einfaches Beispiel, wenn es der erste Fehler ist, möchte ich ihn vielleicht nur für 30 Sekunden in die Warteschlange zurückwerfen. Zweite 1m, dritte 5m, vierte 30m, fünfte 1h, usw. ad nauseam. Um dies zu tun, müssten wir wissen, wie oft es zuvor empfangen wurde, was wir über DeliveryCount (oder eine andere benutzerdefinierte Requisite) verfolgen könnten, aber wenn wir noch kein Receive() ausgeführt hätten, hätten wir das nicht Eigenschaftendaten, um zu ermitteln, wie lange die TTL festgelegt werden soll. –

1

fühlt sich ein bisschen hacky, aber die Lösung kam ich mit ist

try 
{ 
    ... 
} 
catch (Exception ex) 
{ 
    await Task.Delay(30000); 
    throw; 
} 

diese Weise ist es für 30 Sekunden warten, bevor es zu verlassen ermöglicht. Es wird schließlich nach der konfigurierten Anzahl von Malen tot sein.

Ich verwende Azure Webjobs zum Empfangen. Obwohl ich Task.Delay anstelle von Thread.Sleep verwende, scheint es den Thread nicht freizugeben, um ein anderes Element aus der Warteschlange zu verarbeiten, während es wartet (standardmäßig verarbeitet Webjobs 16 parallel).

0

Ich würde den letzten Ansatz bevorzugen, weil es die einfachste Lösung zu sein scheint, die die eingebauten Funktionen des Azure-Servicebusses verwendet. diese

Die Strömung ist:

var newMessage = new BrokeredMessage(); 
// Copy message body and properties from original message... 

var scheduleTimeUtc = DateTimeOffset.UtcNow.Add(...); 
await queueClient.ScheduleMessageAsync(newMessage, scheduleTimeUtc); 

await originalMessage.CompleteAsync() 
+0

Ich denke, dass Sie dies stattdessen tun können BrokeredMessage newMessage = brokeredMsg.Clone(); – granadaCoder

Verwandte Themen