Přehled front nedoručených zpráv ve službě Service Bus

Fronty a odběry témat služby Azure Service Bus poskytují sekundární podfrontu označovanou jako fronta nedoručených zpráv (DLQ). Fronta nedoručených zpráv nemusí být explicitně vytvořena a není možné ji odstranit ani spravovat nezávisle na hlavní entitě.

Tento článek popisuje fronty nedoručených zpráv ve službě Service Bus. Velká část diskuse je ilustrovaná ukázkou fronty mrtvých dopisů na GitHubu.

Fronta nedoručených zpráv

Účelem fronty nedoručených zpráv je uchovávat zprávy, které nelze doručovat žádnému příjemci, ani zprávy, které nelze zpracovat. Zprávy se pak dají z DLQ odebrat a zkontrolovat. Aplikace může uživateli umožnit opravit problémy a znovu odeslat zprávu.

Z pohledu rozhraní API a protokolu je DLQ většinou podobná jakékoli jiné frontě, s tím rozdílem, že zprávy lze odesílat pouze prostřednictvím operace dead-letter nadřazené entity. Kromě toho se doba žití nezohledňuje a zprávu z DLQ nemůžete vrátit. Fronta nedoručených zpráv plně podporuje běžné operace, jako je doručování pomocí pohledového zámku, přijímání a mazání a transakční operace.

Fronta DLQ se nečistí automaticky. Zprávy zůstanou ve frontě DLQ, dokud je explicitně nenačtete z DLQ a nezpracujete nevyřízené zprávy.

Cesta k frontě nedoručených zpráv

Každá fronta a každé předplatné má vlastní dílčí frontu s nedoručenými písmeny. Můžete ho adresovat přímo pomocí následující syntaxe (používá se Azure CLI, REST a nástrojů, jako je Service Bus Explorer):

<queue path>/$deadletterqueue
<topic path>/Subscriptions/<subscription path>/$deadletterqueue

Když používáte knihovnu Azure.Messaging.ServiceBus .NET, tuto cestu sami nevytváříte. Místo toho nastavte ServiceBusReceiverOptions.SubQueue na SubQueue.DeadLetter při vytváření příjemce. Příklad najdete v tématu Příjem zpráv z fronty nedoručených zpráv.

Cesta k přenosové frontě nedoručených zpráv

Pokud zprávu nelze předat do cíle v automatickém přeposílání nebo odesílání prostřednictvím scénářů, zpráva se umístí do fronty přenosu nedoručených zpráv (TDLQ) zdrojové entity, která přeposílala, ne v cílové entitě. Každá fronta nebo předplatné, které přeposílá zprávy, má vlastní podfrontu přenosu nedoručených zpráv, ke které můžete přistupovat přímo pomocí následující syntaxe:

<queue path>/$Transfer/$DeadLetterQueue
<topic path>/Subscriptions/<subscription path>/$Transfer/$DeadLetterQueue

Pokud používáte knihovnu .NET Azure.Messaging.ServiceBus, nastavte ServiceBusReceiverOptions.SubQueue na SubQueue.TransferDeadLetter. Příklad najdete v tématu Příjem zpráv z fronty přenosu nedoručených zpráv.

Počet zpráv DLQ

Získání počtu zpráv ve frontě nedoručené pošty na úrovni tématu nelze použít, protože zprávy nejsou na úrovni tématu. Místo toho, když někdo pošle zprávu do tématu, zpráva se v milisekundách přepošle odběrům tématu a již se nenachází na úrovni tématu. Tedy můžete vidět zprávy v DLQ přidruženém k odběru na dané téma. V následujícím příkladu nástroj Service Bus Explorer ukazuje, že ve frontě nedoručených zpráv (DLQ) je aktuálně 62 zpráv pro předplatné test1.

62 zpráv ve frontě nedoručených zpráv pro odběr test1.

Počet zpráv DLQ můžete získat také pomocí příkazu az servicebus topic subscription showAzure CLI .

Přesouvání zpráv do DLQ

Ve službě Service Bus je několik aktivit, které způsobují, že se zprávy zasílají do fronty nedoručitelných zpráv (DLQ) uvnitř samotného modulu pro zasílání zpráv. Aplikace může také explicitně přesouvat zprávy do DLQ. Do nedoručených zpráv se přidají následující dvě vlastnosti (důvod nedoručených zpráv a popis nedoručených zpráv). Aplikace mohou definovat vlastní kódy pro vlastnost důvodu nedoručených písmen, ale systém nastaví následující hodnoty.

Důvod nedoručených dopisů Popis chyby nedoručených zpráv
HeaderSizeExceeded Velikostní kvóta pro tento datový proud překročila limit.
TTLExpiredException Platnost zprávy vypršela a byla nedoručené. Podrobnosti najdete v části Čas do vypršení platnosti.
Session ID is null Entita s povolenou relací neumožňuje zprávy, jejichž identifikátor relace má hodnotu null.
MaxTransferHopCountExceeded Maximální počet povolených kroků směrování při předávání mezi frontami překročil limit. Tato hodnota je nastavená na hodnotu 4.
MaxDeliveryCountExceeded Zprávu se nepovedlo zpracovat po maximálním počtu pokusů o doručení. Podrobnosti najdete v části Maximální počet doručení.

Čas života

Když ve frontách nebo předplatných povolíte funkci dead-lettering, všechny zprávy s vypršenou platností se přesunou do DLQ. Kód důvodu pro nedoručitelnou zprávu je nastaven na TTLExpiredException. Odložené zprávy se po vypršení jejich platnosti nevyprázdní a přesunou se do fronty nedoručených zpráv. Toto chování je záměrné.

Maximální počet doručení

Počet pokusů o doručení zpráv pro fronty a předplatná Service Bus je omezen. Výchozí hodnota je 10. Kdykoli je zpráva doručena v režimu peek-lock, ale je buď výslovně opuštěna, nebo zámek vypršel, počet doručení zprávy se zvýší. Pokud počet doručení překročí limit, zpráva se přesune do fronty DLQ. Důvod přesunutí zprávy do fronty nedoručených zpráv (DLQ) je nastaven na MaxDeliveryCountExceeded. Toto chování nejde zakázat, ale maximální počet doručení můžete nastavit na velké číslo.

Chyby při zpracování pravidel předplatného

Pokud u výjimek vyhodnocení filtru povolíte dead-letter queue, všechny chyby, ke kterým dochází při spouštění pravidla filtru SQL předplatného, se zachytí v DLQ spolu s problematickou zprávou. Tuto možnost nepoužívejte v produkčním prostředí, kde máte typy zpráv odesílané do tématu, které nemají odběratele, protože to může vést k velkému zatížení zpráv DLQ. Proto se ujistěte, že všechny zprávy odeslané do tématu mají alespoň jedno odpovídající předplatné.

Zpracování nedoručených zpráv na úrovni aplikace

Kromě systémem poskytovaných funkcí pro nedoručené zprávy mohou aplikace používat frontu DLQ k explicitnímu odmítnutí nepřijatelných zpráv. Nepřijatelné zprávy můžou zahrnovat zprávy, které se nedají správně zpracovat kvůli nějakému problému se systémem, zprávám, které obsahují poškozené datové části, nebo zprávy, které selžou ověřování při použití některého schématu zabezpečení na úrovni zpráv.

V .NET volejte metodu ServiceBusReceiver.DeadLetterMessageAsync.

Doporučujeme zahrnout typ výjimky do DeadLetterReason a trasování zásobníku výjimky do DeadLetterDescription, protože to usnadňuje řešení příčin problému, které vedou k nedoručení zpráv. Může to vést k překročení limitu kvóty 256 kB pro úroveň Standard Azure Service Bus. Obor názvů služby Service Bus můžete upgradovat z úrovně Standard na úroveň Premium, abyste měli vyšší kvóty a limity.

Přijímat zprávy z fronty nedoručených zpráv

Chcete-li přijmout zprávu z fronty nedoručených zpráv pomocí knihovny Azure.Messaging.ServiceBus .NET, nastavte při vytváření příjemce ServiceBusReceiverOptions.SubQueue na SubQueue.DeadLetter. Knihovna se za vás postará o adresování podfronty neodeslaných zpráv.

using Azure.Identity;
using Azure.Messaging.ServiceBus;

string fullyQualifiedNamespace = "<NAMESPACE-NAME>.servicebus.windows.net";
string queueName = "<QUEUE-NAME>";

// 1. Create the top-level client. Passwordless authentication is recommended.
await using var client = new ServiceBusClient(fullyQualifiedNamespace, new DefaultAzureCredential());

// 2. Configure options to target the dead-letter sub-queue.
var options = new ServiceBusReceiverOptions
{
    SubQueue = SubQueue.DeadLetter
};

// 3. Create a receiver scoped to the dead-letter queue. For a subscription's
//    dead-letter queue, use: client.CreateReceiver(topicName, subscriptionName, options).
ServiceBusReceiver dlqReceiver = client.CreateReceiver(queueName, options);

// 4. Receive a dead-lettered message.
ServiceBusReceivedMessage dlqMessage = await dlqReceiver.ReceiveMessageAsync();

// 5. Inspect why the message was dead-lettered.
string reason = dlqMessage.DeadLetterReason;
string description = dlqMessage.DeadLetterErrorDescription;

// 6. Complete the message to remove it from the dead-letter queue.
await dlqReceiver.CompleteMessageAsync(dlqMessage);

Stejný vzor funguje i pro frontu nedoručených zpráv pro přenos pomocí SubQueue.TransferDeadLetter. Úplný příklad najdete v tématu Příjem zpráv z fronty přenosu nedoručených zpráv.

Nedoručované dopisy ve scénářích automatického předávání

Zprávy se odesílají do fronty nedoručených zpráv za následujících podmínek:

  • Zpráva prochází více než čtyřmi frontami nebo tématy, které jsou zřetězené.
  • Cílová fronta nebo téma je zakázaná nebo odstraněná.
  • Cílová fronta nebo téma překračují maximální velikost entity.

Zasílání nedoručených dopisů prostřednictvím scénářů

  • Pokud je cílová fronta nebo téma zakázané, zpráva se odešle do fronty přenosu nedoručených zpráv (TDLQ) zdrojové fronty.
  • Pokud cílová fronta nebo entita překročí svou velikost, zpráva se odešle do TDLQ zdrojové fronty.

Počet zpráv čekajících ve frontě nedoručených zpráv pro přenos můžete zjistit přečtením runtime vlastnosti TransferDeadLetterMessageCount zdrojové entity. Další informace najdete v tématu Podrobnosti o počtu zpráv.

Příjem zpráv z fronty přenosu nedoručených zpráv

Fronta nedoručených zpráv přenosu je dílčí frontou zdrojové entity, takže z ní přijímáte zprávy stejným způsobem jako z běžné fronty nedoručených zpráv: nastavíte příjemce pro zdrojovou frontu (nebo předplatné zdrojového tématu) a vyberete dílčí frontu nedoručených zpráv přenosu.

Když používáte knihovnu Azure.Messaging.ServiceBus .NET, nastavte ServiceBusReceiverOptions.SubQueue na SubQueue.TransferDeadLetter při vytváření přijímače. Knihovna se zabývá dílčí frontou přenosu nedoručených zpráv za vás.

using Azure.Identity;
using Azure.Messaging.ServiceBus;

string fullyQualifiedNamespace = "<NAMESPACE-NAME>.servicebus.windows.net";

// The source queue that forwards messages. The transfer dead-letter queue
// lives on this entity, not on the destination.
string sourceQueueName = "<SOURCE-QUEUE-NAME>";

// 1. Create the top-level client. Passwordless authentication is recommended.
await using var client = new ServiceBusClient(fullyQualifiedNamespace, new DefaultAzureCredential());

// 2. Configure options to target the transfer dead-letter sub-queue.
var options = new ServiceBusReceiverOptions
{
    SubQueue = SubQueue.TransferDeadLetter
};

// 3. Create a receiver scoped to the source entity's transfer dead-letter queue.
//    For a subscription that forwards, use:
//    client.CreateReceiver(topicName, subscriptionName, options).
ServiceBusReceiver tdlqReceiver = client.CreateReceiver(sourceQueueName, options);

// 4. Receive a message that failed to transfer to its destination.
ServiceBusReceivedMessage tdlqMessage = await tdlqReceiver.ReceiveMessageAsync();

// 5. Inspect why the message couldn't be transferred.
string reason = tdlqMessage.DeadLetterReason;
string description = tdlqMessage.DeadLetterErrorDescription;

// 6. Complete the message to remove it from the transfer dead-letter queue.
await tdlqReceiver.CompleteMessageAsync(tdlqMessage);

Odesílání nedoručených zpráv, které se mají znovu zpracovat

Jakmile vyřešíte problém, který způsoboval nedoručené zprávy, můžete ji znovu odeslat do fronty nebo tématu, aby se znovu zpracovala. Nejjednodušším přístupem je použít průzkumníka Service Bus na portálu Azure, který umožňuje zobrazit zprávy ve frontě nedoručených zpráv, upravit jejich obsah nebo vlastnosti v případě potřeby a znovu je odeslat – jednotlivě nebo v dávkách. Operátory často dávají přednost tomuto uživatelskému rozhraní, protože zobrazuje, které typy zpráv selhaly, ze kterých zdrojových entit a proč, a přitom stále povoluje dávkové opětovné odeslání.

Další informace o různých způsobech konfigurace nedoručených zpráv při vypršení platnosti zpráv najdete v tématu Povolení nedoručených zpráv pro frontu nebo odběr.