博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Windows Azure: Service Bus Brokered Messaging DeadLetterQueue 使用详解
阅读量:5367 次
发布时间:2019-06-15

本文共 5835 字,大约阅读时间需要 19 分钟。

什么是DeadLetterQueue

DeadLetterQueue的概念不仅仅存在于Service Bus Brokered Messaging 服务中,在各种平台的消息队列中间件中,都包含DeadLetterQueue的概念。DeadLetterQueue是在正常的消息队列之外,由系统生成的一个子队列,用来存储“有问题”的消息。这个“有问题”的消息,可能是指发送端发送失败的消息,或者是接收方处理失败的消息,或者是超期未处理的消息。

DeadLetterQueue in Service Bus Brokered Messaging

在Service Bus Brokered Messaging中,每一个Queue与Subscription都包含一个子队列用以实现DeadLetterQueue,这个子队列由Service Bus系统生成,如图所示:

在以下几种情况中,Message将会被移入DeadLetterQueue:

  1. 消息接收方,在消息被Complete和Abandon之前,显式调用Message的DeadLetter方法,可将消息移入DeadLetter队列;
  2. Queue或Subscription的EnableDeadLetteringOnMessageExpiration设置为true,当消息过期以后,将自动被移入DeadLetter队列;
  3. Subscription的EnableDeadLetteringOnFilterEvaluationExceptions属性设置为true,当消息过滤出现异常时,将自动被移入DeadLetter队列;
  4. 当消息的接收次数超过MaxDeliveryCount设置的值时,将自动被移入DeadLetter队列;

显式调用DeadLetter

什么样的情况需要显示调用DeadLetter方法将消息移入DeadLetter队列呢?我考虑了一个场景,假设接收方是一个订单处理系统,发送方将订单信息包含在消息中进行发送,但是这个接收方只能处理固定区域的订单,对于其他区域的订单无法处理,这时,如果接收到其他区域的订单,则可以暂不处理并将其移入DeadLetter队列,等正常的消息处理完成以后,再来对DeadLetter队列中的订单消息做一些特殊处理。

发送消息:

1: string queueName = "MyQueue";
2: NamespaceManager namespaceClient = NamespaceManager.Create();
3: if (namespaceClient.QueueExists(queueName))
4: {
5:     namespaceClient.DeleteQueue(queueName);
6: }
7: QueueDescription queueDescription = new QueueDescription(queueName);
8: namespaceClient.CreateQueue(queueDescription);
9: 
10: MessagingFactory factory = MessagingFactory.Create();
11: QueueClient queueClient = factory.CreateQueueClient(queueName);
12: CreateAndSendOrderMessage(Guid.NewGuid().ToString(), "Beijing", queueClient);
13: CreateAndSendOrderMessage(Guid.NewGuid().ToString(), "Dalian", queueClient);
14: CreateAndSendOrderMessage(Guid.NewGuid().ToString(), "Guangzhou", queueClient);
15: 
16: Console.WriteLine();
17: Console.WriteLine("Press [Enter] to delete queue and exit.");
18: Console.ReadLine();
19: namespaceClient.DeleteQueue(queueName);
20: factory.Close();
21: queueClient.Close();
1: private static void CreateAndSendOrderMessage(string orderId, string orderRegion, QueueClient sender)
2: {
3:     var message = new BrokeredMessage();
4:     message.Properties.Add("OrderId", orderId);
5:     message.Properties.Add("OrderRegion", orderRegion);
6:     Console.WriteLine("Sending message of order region {0}.", message.Properties["OrderRegion"]);
7:     sender.Send(message);
8: }

 

接收消息:

1: string queueName = "MyQueue";
2: MessagingFactory factory = MessagingFactory.Create();
3: QueueClient queueClient = factory.CreateQueueClient(queueName, ReceiveMode.PeekLock);
4: Console.WriteLine("Reading messages from queue...");
5: BrokeredMessage message = null;
6: while ((message = queueClient.Receive(TimeSpan.FromSeconds(2))) != null)
7: {
8:     string orderRegion = message.Properties["OrderRegion"].ToString();
9:     if (validatedRegion.Contains(orderRegion))
10:     {
11:         Console.WriteLine("Process the message whose order region is {0}", orderRegion);
12:         ProcessMessage(message);
13:         message.Complete();
14:     }
15:     else
16:     {
17:         Console.WriteLine("DeadLetter the message whose order region is {0}", orderRegion);
18:         message.DeadLetter("Invalid Region", string.Format("The order region {0} is invalid", orderRegion));
19:     }
20:     message.Dispose();
21: }
22: queueClient.Close();

处理DeadLetter队列中的消息:

1: string deadLetterQueuePath = QueueClient.FormatDeadLetterPath(queueName);
2: QueueClient deadletterQueueClient = factory.CreateQueueClient(deadLetterQueuePath, ReceiveMode.PeekLock);
3: Console.WriteLine("Reading messages from deadletter queue...");
4: 
5: BrokeredMessage messageInDeadletterQueue = null;
6: while ((messageInDeadletterQueue = deadletterQueueClient.Receive(TimeSpan.FromSeconds(2))) != null)
7: {
8:     LogDeadletterMessage(messageInDeadletterQueue);
9:     messageInDeadletterQueue.Complete();
10:     messageInDeadletterQueue.Dispose();
11: }
12: 
13: deadletterQueueClient.Close();

过期消息

假设我们在创建队列或者Subscription时,将默认的消息存活时间设置为5s(当然也可以给每个消息单独设置TimeToLive),并且将EnableDeadLetteringOnMessageExpiration设置为true,如果为false,则过期消息将被直接删除。

1: string queueName = "MyQueue";
2: NamespaceManager namespaceClient = NamespaceManager.Create();
3: if (namespaceClient.QueueExists(queueName))
4: {
5:     namespaceClient.DeleteQueue(queueName);
6: }
7: QueueDescription queueDescription = new QueueDescription(queueName)
8: {
9:     DefaultMessageTimeToLive = TimeSpan.FromSeconds(5),
10:     EnableDeadLetteringOnMessageExpiration = true
11: };
12: namespaceClient.CreateQueue(queueDescription);

那在消息发送以后,等5s我们再去正常接收消息,会发现没有任何消息,消息因超期被移入了DeadLetter队列中,接收消息代码同显示调用DeadLetter。测试结果如图所示:

消息发送:

消息接收:

接收次数超过MaxDeliveryCount值

我们将Queue或Subscription的MaxDeliveryCount属性设置为2,那么一旦消息被接收的次数到达2次以后将会被移入DeadLetter队列。

1: string queueName = "MyQueue";
2: NamespaceManager namespaceClient = NamespaceManager.Create();
3: if (namespaceClient.QueueExists(queueName))
4: {
5:     namespaceClient.DeleteQueue(queueName);
6: }
7: QueueDescription queueDescription = new QueueDescription(queueName)
8: {
9:     MaxDeliveryCount = 2
10: };
11: namespaceClient.CreateQueue(queueDescription);

接收消息:

1: string queueName = "MyQueue";
2: MessagingFactory factory = MessagingFactory.Create();
3: QueueClient queueClient = factory.CreateQueueClient(queueName, ReceiveMode.PeekLock);
4: Console.WriteLine("Reading messages from queue...");
5: BrokeredMessage message = null;
6: while ((message = queueClient.Receive(TimeSpan.FromSeconds(2))) != null)
7: {
8:     Console.WriteLine("Order Id:{0}", message.Properties["OrderId"]);
9:     message.Abandon();
10:     message.Dispose();
11: }
12: queueClient.Close();

从DeadLette队列中收取消息代码同上。

测试结果:

从图中我们可以看到,总共3个订单消息,每个消息被接收了两次,然后从DeadLetter队列中就能收取到这3条消息。

Filter Evaluation Exception

快崩溃了,一直没能模拟出Filter Evaluation Exception,所以无法为大家提供例证。后期我再补全并上传代码。哪位好心朋友如果清楚Filter Evaluation Exception如何模拟请给我留言,谢谢。

转载于:https://www.cnblogs.com/lijiawei/archive/2013/01/23/2873077.html

你可能感兴趣的文章
使用Html.EditorFor()为文本框加上maxlength,placeholder等属性
查看>>
[转]后缀数组求最长重复子串
查看>>
设计模式——外观模式详解
查看>>
MVC3 控件
查看>>
mysql (一)
查看>>
photoshop图层样式初识1
查看>>
【.NET】使用HtmlAgilityPack抓取网页数据
查看>>
typedef的使用
查看>>
基于位置的本地商铺个性化推荐
查看>>
职场上一个人情商高的十种表现
查看>>
【底层原理】深入理解Cache (下)
查看>>
Elasticsearch安装中文分词插件IK
查看>>
进阶4:常见函数-单行函数
查看>>
简述企业信息化与企业架构关系
查看>>
npoi List 泛型导出
查看>>
流程图怎么画?分享绘制流程图简单方法
查看>>
squid的处理request和reply的流程
查看>>
硬件_陀螺仪
查看>>
三、winForm-DataGridView操作——DataGridView 操作复选框checkbox
查看>>
SSIS的部署和配置
查看>>