Visão geral das filas de mensagens mortas do Barramento de ServiçoOverview of Service Bus dead-letter queues

As filas e as assinaturas de tópico do Barramento de Serviço do Azure fornecem uma subfila secundária chamada DLQ (fila de mensagens mortas).Azure Service Bus queues and topic subscriptions provide a secondary subqueue, called a dead-letter queue (DLQ). A fila de mensagens mortas não precisa ser explicitamente criada e não pode ser excluída ou de alguma forma gerenciada independentemente da entidade principal.The dead-letter queue doesn't need to be explicitly created and can't be deleted or otherwise managed independent of the main entity.

Este artigo descreve as filas de mensagens mortas no Barramento de Serviço.This article describes dead-letter queues in Service Bus. Grande parte da discussão é ilustrada pelo exemplo de Filas de mensagens mortas no GitHub.Much of the discussion is illustrated by the Dead-Letter queues sample on GitHub.

A fila de mensagens mortasThe dead-letter queue

A finalidade da fila de mensagens mortas é manter mensagens que não podem ser entregues a nenhum receptor ou mensagens que não puderam ser processadas.The purpose of the dead-letter queue is to hold messages that can't be delivered to any receiver, or messages that couldn't be processed. As mensagens podem ser removidas da DLQ e inspecionadas.Messages can then be removed from the DLQ and inspected. Um aplicativo pode, com a ajuda de um operador, corrigir problemas e reenviar a mensagem, registrar o fato de que houve um erro e tomar uma medida corretiva.An application might, with help of an operator, correct issues and resubmit the message, log the fact that there was an error, and take corrective action.

De uma perspectiva de API e protocolo, a DLQ é bem semelhante a qualquer outra fila, com exceção de que essas mensagens podem ser enviadas apenas por meio da operação de mensagens mortas da entidade pai.From an API and protocol perspective, the DLQ is mostly similar to any other queue, except that messages can only be submitted via the dead-letter operation of the parent entity. Além disso, a vida útil não é observada, e você não pode colocar uma mensagem em estado morto na DLQ.In addition, time-to-live isn't observed, and you can't dead-letter a message from a DLQ. A fila de mensagens mortas é totalmente compatível com operações transacionais e de entrega de espiada-bloqueio.The dead-letter queue fully supports peek-lock delivery and transactional operations.

Não há limpeza automática da DLQ.There's no automatic cleanup of the DLQ. As mensagens permanecem na DLQ até você recuperá-las de lá explicitamente e chamar Complete() na mensagem morta.Messages remain in the DLQ until you explicitly retrieve them from the DLQ and call Complete() on the dead-letter message.

Contagem de mensagens da DLQDLQ message count

Não é possível obter a contagem de mensagens da fila de mensagens mortas no nível do tópico.It's not possible to obtain count of messages in the dead-letter queue at the topic level. Isso ocorre porque as mensagens não ficam no nível do tópico, a menos que o Barramento de Serviço gere um erro interno.That's because messages don't sit at the topic level unless Service Bus throws an internal error. Em vez disso, quando um remetente envia uma mensagem a um tópico, a mensagem é encaminhada para as assinaturas do tópico em milissegundos e, portanto, não reside mais no nível do tópico.Instead, when a sender sends a message to a topic, the message is forwarded to subscriptions for the topic within milliseconds and thus no longer resides at the topic level. Portanto, você pode ver mensagens na DLQ associada à assinatura do tópico.So, you can see messages in the DLQ associated with the subscription for the topic. No exemplo a seguir, Service Bus Explorer mostra que atualmente há 62 mensagens em DLQ para a assinatura "test1".In the following example, Service Bus Explorer shows that there are 62 messages currently in the DLQ for the subscription "test1".

Contagem de mensagens da DLQ

Você também pode obter a contagem de mensagens DLQ usando o comando da CLI do Azure: az servicebus topic subscription show.You can also get the count of DLQ messages by using Azure CLI command: az servicebus topic subscription show.

Movendo mensagens para a DLQMoving messages to the DLQ

Há várias atividades no Barramento de Serviço que fazem com que as mensagens sejam enviadas por push à DLQ de dentro do próprio mecanismo de mensagens.There are several activities in Service Bus that cause messages to get pushed to the DLQ from within the messaging engine itself. Um aplicativo também pode explicitamente colocar mensagens na DLQ.An application can also explicitly move messages to the DLQ.

Como a mensagem é movida pelo agente, duas propriedades são adicionadas à mensagem, uma vez que o agente chama sua versão interna do método DeadLetter na mensagem: DeadLetterReason e DeadLetterErrorDescription.As the message gets moved by the broker, two properties are added to the message as the broker calls its internal version of the DeadLetter method on the message: DeadLetterReason and DeadLetterErrorDescription.

Os aplicativos podem definir seus próprios códigos para a propriedade DeadLetterReason, mas o sistema define os valores a seguir.Applications can define their own codes for the DeadLetterReason property, but the system sets the following values.

DeadLetterReasonDeadLetterReason DeadLetterErrorDescriptionDeadLetterErrorDescription
HeaderSizeExceededHeaderSizeExceeded A cota de tamanho para este fluxo foi excedida.The size quota for this stream has been exceeded.
TTLExpiredExceptionTTLExpiredException A mensagem expirou e foi colocada no estado de mensagem morta.The message expired and was dead lettered. Confira a seção Excedendo TimeToLive para obter detalhes.See the Exceeding TimeToLive section for details.
A ID da sessão é nula.Session ID is null. A entidade habilitada para sessão não permite uma mensagem cuja identificação de sessão seja nula.Session enabled entity doesn't allow a message whose session identifier is null.
MaxTransferHopCountExceededMaxTransferHopCountExceeded O número máximo de saltos permitidos ao encaminhar entre filas.The maximum number of allowed hops when forwarding between queues. O valor é definido como 4.Value is set to 4.
MaxDeliveryCountExceededExceptionMessageMaxDeliveryCountExceededExceptionMessage A mensagem não pôde ser consumida após o máximo de tentativas da entrega.Message could not be consumed after maximum delivery attempts. Confira a seção Como exceder o MaxDeliveryCount para obter detalhes.See the Exceeding MaxDeliveryCount section for details.

Excedendo MaxDeliveryCountExceeding MaxDeliveryCount

Cada uma das filas e assinaturas tem uma propriedade QueueDescription.MaxDeliveryCount e SubscriptionDescription.MaxDeliveryCount, respectivamente; o valor padrão é 10.Queues and subscriptions each have a QueueDescription.MaxDeliveryCount and SubscriptionDescription.MaxDeliveryCount property respectively; the default value is 10. Sempre que uma mensagem tiver sido entregue em um bloqueio (ReceiveMode.PeekLock), mas tiver sido explicitamente abandonada ou o bloqueio tiver expirado, BrokeredMessage.DeliveryCount será incrementada.Whenever a message has been delivered under a lock (ReceiveMode.PeekLock), but has been either explicitly abandoned or the lock has expired, the message BrokeredMessage.DeliveryCount is incremented. Quando DeliveryCount exceder MaxDeliveryCount, a mensagem será movida para a DLQ, especificando o código de motivo MaxDeliveryCountExceeded.When DeliveryCount exceeds MaxDeliveryCount, the message is moved to the DLQ, specifying the MaxDeliveryCountExceeded reason code.

Esse comportamento não pode ser desabilitado, mas você pode definir MaxDeliveryCount para um número alto.This behavior can't be disabled, but you can set MaxDeliveryCount to a large number.

Excedendo TimeToLiveExceeding TimeToLive

Quando a propriedade QueueDescription.EnableDeadLetteringOnMessageExpiration ou SubscriptionDescription.EnableDeadLetteringOnMessageExpiration for definida como true (o padrão é false), todas as mensagens expiradas serão movidas para a DLQ, especificando o código de motivo TTLExpiredException.When the QueueDescription.EnableDeadLetteringOnMessageExpiration or SubscriptionDescription.EnableDeadLetteringOnMessageExpiration property is set to true (the default is false), all expiring messages are moved to the DLQ, specifying the TTLExpiredException reason code.

As mensagens expiradas só são limpas e movidas para o DLQ quando há pelo menos uma recepção de receptor ativa da fila principal ou da assinatura, e as mensagens adiadas também não serão limpas e movidas para a fila de mensagens mortas depois que elas expirarem.Expired messages are only purged and moved to the DLQ when there is at least one active receiver pulling from the main queue or subscription, and deferred messages will also not be purged and moved to the dead-letter queue after they expire. Esses comportamentos são por design.These behaviours are by design.

Erros ao processar as regras de assinaturaErrors while processing subscription rules

Quando a propriedade SubscriptionDescription.EnableDeadLetteringOnFilterEvaluationExceptions for habilitada para uma assinatura, qualquer erro que ocorra durante as execuções da regra de filtro SQL de uma assinatura será capturado na DLQ com a mensagem ofensiva.When the SubscriptionDescription.EnableDeadLetteringOnFilterEvaluationExceptions property is enabled for a subscription, any errors that occur while a subscription's SQL filter rule executes are captured in the DLQ along with the offending message. Não use essa opção em um ambiente de produção no qual nem todos os tipos de mensagem tenham assinantes.Don't use this option in a production environment in which not all message types have subscribers.

Mensagens mortas no nível de aplicativoApplication-level dead-lettering

Além dos recursos de mensagens mortas fornecidas pelo sistema, os aplicativos podem usar a DLQ para rejeitar explicitamente mensagens inaceitáveis.In addition to the system-provided dead-lettering features, applications can use the DLQ to explicitly reject unacceptable messages. Elas podem incluir mensagens que não puderam ser processadas adequadamente devido a qualquer tipo de problema no sistema, mensagens que mantêm cargas malformadas ou mensagens que falham na autenticação quando algum esquema de segurança no nível de mensagem é usado.They can include messages that can't be properly processed because of any sort of system issue, messages that hold malformed payloads, or messages that fail authentication when some message-level security scheme is used.

Mensagens mortas em cenários de ForwardTo ou SendViaDead-lettering in ForwardTo or SendVia scenarios

Mensagens serão enviadas para a fila de mensagens mortas para transferência sob as seguintes condições:Messages will be sent to the transfer dead-letter queue under the following conditions:

  • Uma mensagem que passe por mais de quatro filas ou tópicos encadeados.A message passes through more than four queues or topics that are chained together.
  • A fila ou o tópico de destino é desabilitado ou excluído.The destination queue or topic is disabled or deleted.
  • O tópico ou a fila de destino excede o tamanho máximo de entidade.The destination queue or topic exceeds the maximum entity size.

Para recuperar essas mensagens mortas, você pode criar um destinatário usando o método utilitário FormatTransferDeadletterPath.To retrieve these dead-lettered messages, you can create a receiver using the FormatTransferDeadletterPath utility method.

ExemploExample

O snippet de código a seguir cria um receptor de mensagem.The following code snippet creates a message receiver. No loop de recebimento da fila principal, o código recupera a mensagem com Receive(TimeSpan.Zero), que solicita ao agente para retornar instantaneamente qualquer mensagem prontamente disponível ou retornar sem resultado.In the receive loop for the main queue, the code retrieves the message with Receive(TimeSpan.Zero), which asks the broker to instantly return any message readily available, or to return with no result. Se o código receber uma mensagem, ele a abandonará imediatamente, o que incrementa a DeliveryCount.If the code receives a message, it immediately abandons it, which increments the DeliveryCount. Depois que o sistema move a mensagem para a DLQ, a fila principal é esvaziada e o loop é encerrado, pois ReceiveAsync retorna null.Once the system moves the message to the DLQ, the main queue is empty and the loop exits, as ReceiveAsync returns null.

var receiver = await receiverFactory.CreateMessageReceiverAsync(queueName, ReceiveMode.PeekLock);
while(true)
{
    var msg = await receiver.ReceiveAsync(TimeSpan.Zero);
    if (msg != null)
    {
        Console.WriteLine("Picked up message; DeliveryCount {0}", msg.DeliveryCount);
        await msg.AbandonAsync();
    }
    else
    {
        break;
    }
}

Caminho para a fila de mensagens mortasPath to the dead-letter queue

É possível acessar a fila de mensagens mortas usando a seguinte sintaxe:You can access the dead-letter queue by using the following syntax:

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

Se você estiver usando o SDK do .NET, poderá obter o caminho para a fila de mensagens mortas usando o método SubscriptionClient.FormatDeadLetterPath().If you're using the .NET SDK, you can get the path to the dead-letter queue by using the SubscriptionClient.FormatDeadLetterPath() method. Esse método usa o nome do tópico/assinatura e os sufixos com /$DeadLetterQueue.This method takes the topic name/subscription name and suffixes with /$DeadLetterQueue.

Próximas etapasNext steps

Confira os artigos a seguir para obter mais informações sobre as filas do Barramento de Serviço:See the following articles for more information about Service Bus queues: