MSMQ—确认队列和响应队列
一、MSMQ——消息的响应(响应队列)
如果需要从接收程序中获得比确认消息更多的信息(消息确认参考二),就可以使用响应队列。响应队列类似于一般队列,但原始发生程序吧该队列用作接收程序,原始接收
程序把响应队列作用于发生程序。
发送程序必须用 Message 类的 ResponseQueue 属性指定响应队列。在响应消息中,把 CorrelationId 属性设置为原始的消息ID,这样,客户端就知道该条应答属于哪条消息。
这类似于确认队列。响应消息用 MessageQueue 对象的 Send() 方法发送,MessageQueue 对象从 ResponseQueue 属性中返回。
当消息队列生成确认或报告消息时,它使用相关标识符属性来指定原始消息的消息标识符。 这样,相关标识符就可将报告或确认消息与原始消息关联起来。
发送应用程序然后可以进行匹配的确认或与原始消息的报表通过使用CorrelationId属性来标识原始消息的Id属性。
连接器应用程序还必须设置 CorrelationId 属性发送到原始消息的消息标识符的确认消息和报告的消息。
当你的应用程序将响应消息发送到发送应用程序时,可以设置 CorrelationId 响应消息的原始消息的消息标识符的属性。 发送应用程序然后可以将响应消息与已发送的消息进行匹配。
/// <summary>
/// 消息队列
/// </summary>
private MessageQueue messageQueue
{
get
{
string path = ".\\private$\\temp";
if (MessageQueue.Exists(path))
{
//如果存在指定路径的消息队列,则获取
return new MessageQueue(path);
}
else
{
//不存在,则创建新的
return MessageQueue.Create(path);
}
}
} /// <summary>
/// 获取返回消息
/// </summary>
public void ReciveMessage()
{
while (true)
{
//Message.Receive()是同步进行的,如果队列中没有消息,会阻塞当前线程
Message message = messageQueue.Receive(); message.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });
string msg = message.Body.ToString(); var responeMessage = new Message("responeMessage")
{
//原始消息id
CorrelationId = message.Id
};
message.ResponseQueue = GetResponseQueue();
//获取或设置一个值,该值指示发送方 ID 是否应附在消息中。
//message.AttachSenderId = true;
//发生响应消息
message.ResponseQueue.Send(responeMessage);
Console.WriteLine(msg);
}
}
获取响应消息,获得原消息id进行匹配
/// <summary>
/// 获取响应队列
/// </summary>
/// <returns></returns>
public MessageQueue GetResponseQueue()
{
//路径
string path = ".\\private$\\ResponseQueue";
if (MessageQueue.Exists(path))
{
//如果存在指定路径的消息队列,则获取
return new MessageQueue(path);
}
else
{
//不存在,则创建新的
return MessageQueue.Create(path);
}
} /// <summary>
/// 获取返回队列消息
/// </summary>
public void ReciveResponseQueue()
{
while (true)
{
var myQueue = GetResponseQueue();
//设置将获取 CorrelationId 的MessageReadPropertyFilter设为TRUE
myQueue.MessageReadPropertyFilter.CorrelationId = true;
//Message.Receive()是同步进行的,如果队列中没有消息,会阻塞当前线程
Message message = myQueue.Receive(); message.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });
string msg = message.Body.ToString();
//获取原始消息的Id
var _correlationId = message.CorrelationId;
message.ResponseQueue = GetResponseQueue(); Console.WriteLine(msg);
}
}
二、MSMQ——消息的确认
可以将MessageQueue对象设置为生成确认消息,能通知消息发送者消息是否已经成功传递。
有两种主要的确认类型:
·消息到达目标队列的确认
·目标应用程序从队列中检索到消息的确认
确认是通过向队列发送新消息来处理的。这种情况下,确认消息从目标队列发送到一个特殊类型的队列中:管理队列。确认消息不同于标准消息,因为它们不包含正文;在确认中,消息头中的信息最重要。
这里以一个示例来演示一下:
(一)新建管理队列
private MessageQueue CreateAdminQueue()
{
string trPath = @".\Private$\selfAdminQueue";
MessageQueue _queue;
if (!MessageQueue.Exists(trPath))
return MessageQueue.Create(trPath);
_queue = new MessageQueue(trPath);
return _queue;
}
(二)传递消息
public void SendConfirmMessage(string strMsg)
{
MessageQueue _queue = CreateQueue();
Message _message = new Message(strMsg);
_message.AdministrationQueue = CreateAdminQueue();
_message.AcknowledgeType =
AcknowledgeTypes.PositiveReceive
| AcknowledgeTypes.PositiveArrival;
_queue.Send(_message);
}
·设置AdminstrationQueue的属性。这个属性是用来设置和获取接收消息队列的确认消息的队列。
·设置确认消息属性AcknowledgeType。这个属性是用来设置和获取返回给发送方消息确认的类型,它是个枚举类型。枚举值:
PositiveArrival |
一个掩码,用于在原始消息到达队列时请求肯定确认。 |
PositiveReceive |
一个掩码,用于在成功从队列检索到原始消息时请求肯定确认。 |
NegativeReceive |
一个掩码,用于当未能从队列接收原始消息时请求否定确认。 |
None |
一个掩码,用于请求不发送任何确认消息(无论是肯定的还是否定的)。 |
NotAcknowledgeReachQueue |
一个掩码,用于在原始消息不能到达队列时请求否定确认。当到达队列时间计时器过期时或不能对消息进行身份验证时,可能请求否定确认。 |
NotAcknowledgeReceive |
一个掩码,用于当发生错误时请求否定确认,防止在其接收时间计时器过期前从队列接收原始消息。 |
FullReachQueue |
一个掩码,用于在原始消息到达队列时请求肯定确认,或者用于到达队列时间计时器过期后请求否定确认,或者用于不能对原始消息进行身份验证时请求否定确认。 |
FullReceive |
一个掩码,用于在接收时间计时器过期前从队列收到原始消息时请求肯定确认,否则请求否定确认。 |
(三)接收方
public string GetNormalMessage()
{
MessageQueue _queue = CreateQueue();
_queue.Formatter =
new XmlMessageFormatter(new Type[] { typeof(string) });
Message _message = _queue.Receive();
return _message.Id;
}
接收消息正常接收。然后得到消息的Id,通过Id来获取在管理队列中的管理消息的信息
(四)管理队列消息
public void GetAcknowledgmentMessage(string strMsgId)
{
MessageQueue _queue = CreateAdminQueue();
_queue.MessageReadPropertyFilter.CorrelationId = true;
_queue.MessageReadPropertyFilter.Acknowledgment = true;
try
{
while (_queue.PeekByCorrelationId(strMsgId) != null)
{
Message myAcknowledgmentMessage =
_queue.ReceiveByCorrelationId(strMsgId);
Console.WriteLine("Correlation Id: "
+ myAcknowledgmentMessage.CorrelationId.ToString());
Console.WriteLine("Id: "
+ myAcknowledgmentMessage.Id.ToString());
Console.WriteLine("Acknowledgment Type: "
+ myAcknowledgmentMessage.Acknowledgment.ToString());
}
}
catch
{ }
}
通过消息标识来检索管理队列,检索成功打印信息。确认类型Acknowledgment用于指定尝试的消息传递的结果。它是个枚举:
None |
该消息不是确认消息。 |
AccessDenied |
一个否定到达确认,它指示发送应用程序不具有将消息发送到目标队列所需的权限。 |
BadDestinationQueue |
一个否定到达确认,它指示目标队列不可用于发送应用程序。 |
BadEncryption |
一个否定到达确认,它指示目标队列管理器未能解密私有消息。 |
BadSignature |
一个否定到达确认,它指示原始消息的数字签名无效并且未能由消息队列进行身份验证。 |
CouldNotEncrypt |
一个否定到达确认,它指示源队列管理器未能加密私有消息。 |
HopCountExceeded |
一个否定到达确认,它指示已超出了原始消息的跳数(跳数指示中间服务器的数目)。 |
NotTransactionalQueue |
一个否定到达确认,它指示已将事务性消息发送到非事务性队列。 |
NotTransactionalMessage |
一个否定到达确认,它指示非事务性消息被发送到了事务性队列。 |
Purged |
一个否定到达确认,它指示消息在到达其目标队列前已被清除。 |
QueueDeleted |
一个否定读取确认,它指示在可以读取消息前队列已被删除。 |
QueueExceedMaximumSize |
一个否定到达确认,它指示原始消息因其目标队列已满而未被传送。 |
QueuePurged |
一个否定读取确认,它指示在可以读取消息前队列已被清除。 |
ReachQueue |
一个肯定到达确认,它指示原始消息已到达其目标队列。 |
ReachQueueTimeout |
一个否定到达确认,它指示在原始消息可到达目标队列前到达队列时间计时器或接收时间计时器已过期。 |
ReceiveTimeout |
一个否定读取确认,它指示在其接收时间计时器过期前没有从队列接收原始消息。 |
Receive |
一个肯定读取确认,它指示原始消息已由接收应用程序接收 |
(五)流程
·当向消息队列传递消息时,同时向管理队列传递了消息(当消息队列收到消息后,管理队列中也会收到消息)。此时的消息是:消息已经到达消息队列。(在管理队列中的消息是不带包体正文的,所以说头最重要。)
·当从消息队列中接收到消息后(此时消息的标识已经读出),消息队列消息就会清空(Revceive的)。然后在管理队列中就会再多一条管理消息,来标示:消息已经被接收。
·当处理管理队列消息时,会按消息标识来处理管理队列消息。
MSMQ—确认队列和响应队列的更多相关文章
- PHP电商订单自动确认收货redis队列
一.场景 之前做的电商平台,用户在收到货之后,大部分都不会主动的点击确认收货,导致给商家结款的时候,商家各种投诉,于是就根据需求,要做一个订单在发货之后的x天自动确认收货.所谓的订单自动确认收货,就是 ...
- 三次握手 四次握手 原因分析 TCP 半连接队列 全连接队列
小结 1. 三次握手的原因:保证双方收和发消息功能正常: [生活模型] "请问能听见吗""我能听见你的声音,你能听见我的声音吗" [原理]A先对B:你在么?我在 ...
- RabbitMQ使用 prefetch_count优化队列的消费,使用死信队列和延迟队列实现消息的定时重试,golang版本
RabbitMQ 的优化 channel prefetch Count 死信队列 什么是死信队列 使用场景 代码实现 延迟队列 什么是延迟队列 使用场景 实现延迟队列的方式 Queue TTL Mes ...
- Java多线程:队列与阻塞队列
1. 什么是阻塞队列 阻塞队列(BlockingQueue)是 Java 5 并发新特性中的内容,阻塞队列的接口是 java.util.concurrent.BlockingQueue,它提供了两个附 ...
- 为什么使用消息队列?消息队列有什么优点和缺点?Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么优点和缺点?
面试题 为什么使用消息队列? 消息队列有什么优点和缺点? Kafka.ActiveMQ.RabbitMQ.RocketMQ 都有什么区别,以及适合哪些场景? 面试官心理分析 其实面试官主要是想看看: ...
- RabbitMQ六种队列模式-简单队列模式
前言 RabbitMQ六种队列模式-简单队列 [本文]RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主 ...
- RabbitMQ从零到集群高可用(.NetCore5.0) - 死信队列,延时队列
系列文章: RabbitMQ从零到集群高可用(.NetCore5.0) - RabbitMQ简介和六种工作模式详解 RabbitMQ从零到集群高可用(.NetCore5.0) - 死信队列,延时队列 ...
- RabbitMQ 入门系列:10、扩展内容:延时队列:延时队列插件及其有限的适用场景(系列大结局)。
系列目录 RabbitMQ 入门系列:1.MQ的应用场景的选择与RabbitMQ安装. RabbitMQ 入门系列:2.基础含义:链接.通道.队列.交换机. RabbitMQ 入门系列:3.基础含义: ...
- C ~ 链式队列与循环队列
此处的链式与循环队列可以应用于BFS和树的层序遍历.下面是对其结构和基本操作的程序描述. 1.循环队列 解决循环队列的队空和队满的方法: [1].增加一个参数count,用来记录数组中当前 ...
随机推荐
- python 迭代器 一个奇怪的解决方法
一般我们在类里面写迭代器都是如下写法: class IterableSomthing: def __iter__(self): return self def __next__(self): retu ...
- (转)Unity_什么是Draw Call? 什么是Batch?
開發遊戲時,一定被時時提醒要減少 Draw Call,當然UNITY也不例外,打開Game Window裡的 Stats,可以看到 Draw Call 與 Batched 的數字.但到底甚麼是 Dra ...
- direnv 一个强大的环境变量管理工具
direnv 是一个基于golang 编写的强大的环境变量管理工具,可以帮助我们简化环境变量管理,而且 支持的平台比较多. 基本使用 下载二进制软件包 https://github.com/dir ...
- ftruncate
普通文件或共享内存区的大小都可以通过该函数修改 #include <unistd.h> int ftruncate(int fd,off_t leght); //成功返回0失败返回-1 对 ...
- MSMQ .NET下的应用
Message Message是MSMQ的数据存储单元,我们的用户数据一般也被填充在Message的body当中,因此很重要,让我们来看一看其在.net中的体现,如图: 在图上我们可以看见,Messa ...
- HanLP 自然语言处理 for nodejs
HanLP 自然语言处理 for nodejs ·支持中文分词(N-最短路分词.CRF分词.索引分词.用户自定义词典.词性标注),命名实体识别(中国人名.音译人名.日本人名.地名.实体机构名识别),关 ...
- v4l2框架分析
参考:https://www.cnblogs.com/fengong/p/4424823.html http://www.cnblogs.com/fengong/p/4424895.html 一 ...
- Azkaban各种类型的Job编写
一.概述 原生的 Azkaban 支持的plugin类型有以下这些: command:Linux shell命令行任务 gobblin:通用数据采集工具 hadoopJava:运行hadoopMR任务 ...
- iOS9.3描述文件怎么安装
iOS9.3 beta描述文件安装教程:1.复制以下地址:http://bbs.feng.com/plugin.php?id=attachment_download:tongji&aid=11 ...
- python笔记(三)---文件读写、修改文件内容、处理json、函数
文件读写(一) #r 只读,打开文件不存在的话,会报错 #w 只写,会清空原来文件的内容 #a 追加写,不会请求,打开的文件不存在的话,也会帮你新建的一个文件 print(f.read()) #获取到 ...