上篇博文中我们介绍了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. MaltReport2:基于 OpenDocument/OpenOfficeXML 的报表引擎

    MaltReport 是我几年前写的开源单据.报表引擎,最近进行了较大的更新,尤其是几年来在生产项目中应用取得了非常好的效果,特别写篇介绍文字给大家分享一下. 首先先介绍几个名词: OpenDocum ...

  2. Vue.js 系列教程 ①

    原文:intro-to-vue-1-rendering-directives-events 译者:nzbin 如果要我用一句话描述使用 Vue 的经历,我可能会说“它如此合乎常理”或者“它提供给我需要 ...

  3. String,StringBuffer,StringBuilder个人认为较重要的区别

        今天在整理不可变对象知识点时,突然看到了String,StringBuffer,StringBuilder三者的区别,这里就挑一些我认为比较重要的点记录一下,方便日后查看.     Strin ...

  4. 移动HTML5前端性能优化总结

    概述 1. PC优化手段在Mobile侧同样适用 2. 在Mobile侧我们提出三秒种渲染完成首屏指标 3. 基于第二点,首屏加载3秒完成或使用Loading 4. 基于联通3G网络平均338KB/s ...

  5. Docker网络代理设置

    背景 在一些实验室环境,服务器没有直接连接外网的权限,需要通过网络代理.我们通常会将网络代理直接配置在/etc/environment./etc/profile之类的配置文件中,这对于大部分操作都是可 ...

  6. ABP入门系列(11)——编写单元测试

    ABP入门系列目录--学习Abp框架之实操演练 源码路径:Github-LearningMpaAbp 1. 前言 In computer programming, unit testing is a ...

  7. Spring Mvc + Easyui中根据查询结果导出文件

    项目是典型的SpringMvc + Easyui,需求是前台页面根据查询条件导出生成CSV文件. 基本流程是:前台页面通过表单提交的方式,请求后台,后台接受到查询参数,根据查询参数查询到数据集合,最后 ...

  8. configparser配置文件模块

    1.configparser的作用 mysql等很多文件的配置如下: [DEFAULT]ServerAliveInterval = 45Compression = yesCompressionLeve ...

  9. UIView和layer的关系

    UIView和layer的关系 UIView是layer的代理 View的根layer ---也就是说view本身自带一个layer, 这个layer 我们叫它根layer 所有视图显示是因为继承UI ...

  10. AR入门系列-在vuforia官网的使用-01-史上最详细AR入门教程

    使用高通的vuforiaSDK 网址:https://developer.vuforia.com/ 我们想要使用vuforia首先得注册一个账号 网站会发送邮件给你的邮箱 点击验证链接,验证邮箱 出现 ...