上篇博文中我们介绍了Azure Messaging的重复消息机制、At most once 和At least once.

Azure Messaging-ServiceBus Messaging消息队列技术系列5-重复消息:at-least-once at-most-once

本文中我们主要研究并介绍Azure Messaging的消息回执机制:实际应用场景:

同步收发场景下,消息生产者和消费者双向应答模式,例如:张三写封信送到邮局中转站,然后李四从中转站获得信,然后在写一份回执信,放到中转站,然后张三去取,当然张三写信的时候就得写明回信地址。还

有,生成订单编号场景,发送一个生成订单编号的消息,消息消费者接收生成订单编号的消息,并通过消息回执返回。

Azure Messaging的消息回执机制主要通过:基于带会话的Queue/Topic、SessionId、ReplyTo属性来实现

在代码实现中,我们需要:

1. 两个工作线程,一个线程用于消息发送和接收回执消息,一个线程用于消息接收和发送消息回执。

2. 一个会话标识:ReceiptSession  

3. 两个队列Queue:RequestQueue:发送消息、接收消息,ResponseQueue:发送回执消息,接收回执消息。

直接Show Code:

首先,我们在ServiceBusMQManager增加一个线程安全的创建带回话的QueueClient方法:

private static object syncObj = new object();
/// <summary>
/// 获取要求会话带Session的QueueClient
/// </summary>
/// <param name="queueName">队列名称</param>
/// <returns>QueueClient</returns>
public QueueClient GetSessionQueueClient(string queueName)
{
var namespaceClient = NamespaceManager.Create();
if (!namespaceClient.QueueExists(queueName))
{
lock (syncObj)
{
if (!namespaceClient.QueueExists(queueName))
{
var queue = new QueueDescription(queueName) { RequiresSession = true };
namespaceClient.CreateQueue(queue);
}
}
} return QueueClient.Create(queueName, ReceiveMode.ReceiveAndDelete);
}

然后我们定义一些常量:

        private static readonly string ReplyToSessionId = "ReceiptSession";

        const double ResponseMessageTimeout = 20.0;

        private static readonly string requestQueueName = "RequestQueue";

        private static readonly string responseQueueName = "ResponseQueue";

实现发送并接收回执消息的方法:

        /// <summary>
/// 发送并接收回执消息
/// </summary>
/// <param name="bills"></param>
public static void SendMessage()
{
var manager = new ServiceBusUtils();
var responseClient = manager.GetSessionQueueClient(responseQueueName);
var requestClient = manager.GetSessionQueueClient(requestQueueName); var messsageReceiver = responseClient.AcceptMessageSession(ReplyToSessionId);
var order = CreateSalesOrder(); //发送消息
var message = new BrokeredMessage(order);
message.Properties.Add("Type", order.GetType().ToString());
message.SessionId = ReplyToSessionId;
message.MessageId = "OrderMessage001";
message.ReplyTo = responseQueueName;
requestClient.Send(message);
Console.WriteLine("Send message: " + message.MessageId + ", SalesOrder ID: " + order.OrderID); //接收消息回执
var receivedMessage = messsageReceiver.Receive(TimeSpan.FromSeconds(ResponseMessageTimeout * )); var receivedOrder = receivedMessage.GetBody<SalesOrder>();
Console.WriteLine("Receive receipt message: " + receivedMessage.MessageId + ", SalesOrder ID: " + receivedOrder.OrderID);
messsageReceiver.Close();
}

实现接收消息并发送回执方法:

 1         /// <summary>
/// 接收消息并回执
/// </summary>
public static void ReceiveMessage()
{
var manager = new ServiceBusUtils(); var requestClient = manager.GetSessionQueueClient(requestQueueName);
var session = requestClient.AcceptMessageSession();
var requestMessage = session.Receive(); if (requestMessage != null)
{
var receivedOrder = requestMessage.GetBody<SalesOrder>();
Console.WriteLine("Receive message: " + requestMessage.MessageId + ", SalesOrder ID: " + receivedOrder.OrderID); var responseMessage = new BrokeredMessage(receivedOrder);
responseMessage.Properties.Add("Type", receivedOrder.GetType().ToString());
responseMessage.ReplyToSessionId = ReplyToSessionId;
responseMessage.MessageId = "ResponseOrderMessage001";
responseMessage.SessionId = requestMessage.SessionId; //发送回执消息
var responseClient = manager.GetSessionQueueClient(requestMessage.ReplyTo);
responseClient.Send(responseMessage);
Console.WriteLine("Send receipt message: " + responseMessage.MessageId + ", SalesOrder ID: " + receivedOrder.OrderID);
}
}

Main方法中,启动两个工作线程:一个线程用于消息发送和接收回执消息,一个线程用于消息接收和发送消息回执。

因为涉及到Azure Messaging中队列的第一次创建,Azure Messaging是不支持多个请求同时创建同一个队列的,因此,我们两个线程间做一个简单的Task.Delay(3000).Wait();

         static void Main(string[] args)
{
var sendTask = Task.Factory.StartNew(() => { SendMessage(); });
Task.Delay().Wait();
var receiveTask = Task.Factory.StartNew(() => { ReceiveMessage(); }); Task.WaitAll(sendTask, receiveTask); Console.ReadKey();
}

我们看看程序输出:

Azure 服务总线中的队列:

可以看出:Azure Messaging-ServiceBus Messaging 基于带会话的Queue/Topic、SessionId、ReplyTo属性来实现消息回执机制。

周国庆

2017/3/23

Azure Messaging-ServiceBus Messaging消息队列技术系列6-消息回执的更多相关文章

  1. Azure Messaging-ServiceBus Messaging消息队列技术系列-索引篇

    Azure Messaging ServiceBus Messaging相关的技术系列,最近已经整理了不少了,统一做一个索引链接,置顶. 方便查找,并后续陆陆续续再增加. 学习消息队列技术,可以先看第 ...

  2. Azure Messaging-ServiceBus Messaging消息队列技术系列3-消息顺序保证

    上一篇:Window Azure ServiceBus Messaging消息队列技术系列2-编程SDK入门  http://www.cnblogs.com/tianqing/p/5944573.ht ...

  3. Azure Messaging-ServiceBus Messaging消息队列技术系列4-复杂对象消息是否需要支持序列化和消息持久化

    在上一篇中,我们介绍了消息的顺序收发保证: Azure Messaging-ServiceBus Messaging消息队列技术系列3-消息顺序保证 在本文中我们主要介绍下复杂对象消息是否需要支持序列 ...

  4. Azure Messaging-ServiceBus Messaging消息队列技术系列8-服务总线配额

    上篇博文中我们介绍了Azure ServiceBus Messaging的消息事务机制: Azure Messaging-ServiceBus Messaging消息队列技术系列7-消息事务(2017 ...

  5. Azure Messaging-ServiceBus Messaging消息队列技术系列5-重复消息:at-least-once at-most-once

    上篇博客中,我们用实际的业务场景和代码示例了Azure Messaging-ServiceBus Messaging对复杂对象消息的支持和消息的持久化: Azure Messaging-Service ...

  6. Window Azure ServiceBus Messaging消息队列技术系列1-基本概念和架构

    前段时间研究了Window Azure ServiceBus Messaging消息队列技术,搞了很多技术研究和代码验证,最近准备总结一下,分享给大家. 首先,Windows Azure提供了两种类型 ...

  7. Window Azure ServiceBus Messaging消息队列技术系列2-编程SDK入门

    各位,上一篇基本概念和架构中,我们介绍了Window Azure ServiceBus的消息队列技术的概览.接下来,我们进入编程模式和详细功能介绍模式,一点一点把ServiceBus技术研究出来. 本 ...

  8. Azure Messaging-ServiceBus Messaging消息队列技术系列1-基本概念和架构

    前段时间研究了Window Azure ServiceBus Messaging消息队列技术,搞了很多技术研究和代码验证,最近准备总结一下,分享给大家. 首先,Windows Azure提供了两种类型 ...

  9. Azure Messaging-ServiceBus Messaging消息队列技术系列2-编程SDK入门

    各位,上一篇基本概念和架构中,我们介绍了Window Azure ServiceBus的消息队列技术的概览.接下来,我们进入编程模式和详细功能介绍模式,一点一点把ServiceBus技术研究出来. 本 ...

随机推荐

  1. 进程——wait与waitpid、僵尸进程与孤儿进程

    僵尸进程:子进程终止了,但是父进程没有回收子进程的资源PCB.使其成为僵尸进程 孤儿进程:父进程先与子进程结束了,使得子进程失去了父进程,这个时候子进程会被1号进程init进程领养,成为孤儿进程 为了 ...

  2. bcnf范式

    3.5范式--bcnf范式到底是什么呢? 对于bcnf范式,通过查阅资料,我的理解是--主键依赖的去除.比如说:一个仓库管理的表格,有以下属性(管理员编号,仓库号,货物编号,货物数量)其中每个管理员管 ...

  3. ReactNative入门(1)初识ReactJs

    现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我,下面来跟我一起领 ...

  4. 在IntelliJ IDEA 13中配置OpenCV的Java开发环境

    准备工作: 下载IDEA 13(这里以版本13为例,后面简称IDEA): 下载Java JDK(用于配置基本的Java开发环境): 下载OpenCV 2.4.9(这里以版本2.4.9为例,据这篇文章说 ...

  5. HTML学习三

    今天主要学习的为JS和HTML标签的一起使用: 一.重定向: <html> <head> <title>JavaScript1</title> < ...

  6. WP8.1开发中ListView控件加载图列表的简单使用(1)

    我也是刚接触WP编程没几个月,就是在这段时间一直闲着没事,然后又比较喜欢WP这款系统,就学习了WP这方面的开发言语,自学是很困难的,掌握这方面的资料不多,很初级,就是自己在网上找资料学习过程中,看到别 ...

  7. 每天一个linux命令(36)--vmstat命令

    vmstat 是 Virtual Memory Statistics(虚拟内存统计)的缩写,可对操作系统的虚拟内存.进程.CPU活动进行监控.他是对系统的整体情况进行统计,不足之处是无法对某个进程进行 ...

  8. 细谈position属性:static、fixed、relative与absolute

    学习WEB有些时日了,对DOM中的定位概念有些模糊,特地花了一个下午的时间搜资料.整理写下这篇随笔. 首先,我们要清楚一个概念:文档流. 简单的讲,就是窗体自上而下分成一行一行,并在每行中按照从左到右 ...

  9. AIO75产品特征与优势

    第一章 系统一体化 AIO7的核心流程由供应链.生产制造.财务成本及自动化办公构成,是迄今为止国内最完善的ERP.OA .HR .MES一体化产品.通过CRM(客户关系)及DRP(分销)扩充出“营销通 ...

  10. PCB行业版特色功能展示

    普实PCB行业版,专为PCB行业需求而定制.秉承一体化.集团化.移动化为设计理念,采用互联网技术.云计算技术.移动应用技术开发的新一代系统帮助PCB企业创新管理模式.引领商业变革!系统从接到订单开始, ...