Azure Messaging-ServiceBus Messaging

上篇博文中我们介绍了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(1); //发送消息
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 * 2)); var receivedOrder = receivedMessage.GetBody<SalesOrder>();
Console.WriteLine("Receive receipt message: " + receivedMessage.MessageId + ", SalesOrder ID: " + receivedOrder.OrderID);
messsageReceiver.Close();
}

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

 1         /// <summary>
2 /// 接收消息并回执
3 /// </summary>
4 public static void ReceiveMessage()
5 {
6 var manager = new ServiceBusUtils();
7
8 var requestClient = manager.GetSessionQueueClient(requestQueueName);
9 var session = requestClient.AcceptMessageSession();
10 var requestMessage = session.Receive();
11
12 if (requestMessage != null)
13 {
14 var receivedOrder = requestMessage.GetBody<SalesOrder>();
15 Console.WriteLine("Receive message: " + requestMessage.MessageId + ", SalesOrder ID: " + receivedOrder.OrderID);
16
17 var responseMessage = new BrokeredMessage(receivedOrder);
18 responseMessage.Properties.Add("Type", receivedOrder.GetType().ToString());
19 responseMessage.ReplyToSessionId = ReplyToSessionId;
20 responseMessage.MessageId = "ResponseOrderMessage001";
21 responseMessage.SessionId = requestMessage.SessionId;
22
23 //发送回执消息
24 var responseClient = manager.GetSessionQueueClient(requestMessage.ReplyTo);
25 responseClient.Send(responseMessage);
26 Console.WriteLine("Send receipt message: " + responseMessage.MessageId + ", SalesOrder ID: " + receivedOrder.OrderID);
27 }
28 }

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

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

 1         static void Main(string[] args)
2 {
3 var sendTask = Task.Factory.StartNew(() => { SendMessage(); });
4 Task.Delay(3000).Wait();
5 var receiveTask = Task.Factory.StartNew(() => { ReceiveMessage(); });
6
7 Task.WaitAll(sendTask, receiveTask);
8
9 Console.ReadKey();
10 }

我们看看程序输出:

Azure 服务总线中的队列:

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

Azure Messaging-ServiceBus Messaging的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. Azure Messaging

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

  10. Storm-源码分析- Messaging (backtype.storm.messaging)

    先定义两个接口和一个类 TaskMessage类本身比较好理解, 抽象storm的message格式 对于IContext, 注释也说了, 定义messaging plugin, 通过什么渠道去发送m ...

随机推荐

  1. javascript保存变量到本地文件

    最近用echarts在做可视化,好多实例都有一大堆数据,想着把数据保存到本地,有什么比较方便又可靠的办法呢? 将下边代码粘贴到浏览器的控制台 (function(console){ console.s ...

  2. Day1:If else流程判断

    一.if...else语句 if 条件成立: 执行条件成立后的代码 else: 执行条件不成立的代码 注:注意有冒号,python会强制缩进!一般语句都必须顶格写,缩进是缩进一个tab键,等于4个空格 ...

  3. 【剑指offer】对面和相等的正方体

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/26509459 剑指offer上的全排列相关题目. 输入一个含有8个数字的数组.推断有么有可 ...

  4. OC的DES加密,使与java的Cipher类用DES/CBC/PKCS5Padding方式的加密结果同样

    问题说明: 近期用到DES加密,而且要与java的Cipher类加密的结果保持一致.没研究过java的Cliper,但工作中Cipher依据DES/CBC/PKCS5Padding加密方式生成了一个字 ...

  5. Android 用SQLite 使用 CursorLoader 中的数据填充列表视图

    我做了简单的测试应用程序基于此示例.有一个按钮,插入到数据库和列表视图的数据.都是在 MainActivity 中.在原来的代码是restartLoader() 仅从调用 onResume() ,但它 ...

  6. 【例题5-8 UVA - 400】Unix ls

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 设n个字符串中出现的最长的为len; 最后一列能容纳len个字符,然后前面的列能容纳len+2个字符. 每行最多60个字符. 按照这 ...

  7. programming-challenges Crypt Kicker (110204) 题解

    我的解答,可是复杂度不是非常惬意,是一个指数级的复杂度.可是測试数据比較弱,还是ac了.在网上找了找.都是brute force的解法,不知道有没有更好的解法. 解答中犯了两个错误,第一个.map&l ...

  8. iOS开发 - Quartz2D画图

    Quartz 2D简单介绍 是一个二维画图引擎,同一时候支持iOS和Mac系统 Quartz 2D能完毕的工作 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图像) 读取\生成 ...

  9. 部分和(partial sum)在算法求解中的作用

    C++ 的 STL 库的 <numeric> 头文件的 partial_sum 函数已实现了对某一序列的 partial sum. partial_sum(first, last, des ...

  10. 数据结构与算法实验题 4.2 Who is the strongest

    数据结构与算法实验题 4.2 Who is the strongest ★实验任务 在神奇的魔法世界,召唤师召唤了一群的魁偶.这些魁偶排成一排,每个魁偶都有一个 战斗值.现在该召唤师有一个技能,该技能 ...