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,用来记录数组中当前 ...
随机推荐
- 【开发】iOS入门 - XCode快捷键
XCode使用第一天,从熟悉快捷键开始... 搜索相关的快捷键: 搜文件.类和方法 - Command + Shift + O 搜字符串 - Command + Shift + F 定位文件 - Co ...
- 10. Firewalls (防火墙 2个)
Netfilter是在标准Linux内核中实现的强大的包过滤器. 用户空间iptables工具用于配置. 它现在支持数据包过滤(无状态或有状态),各种网络地址和端口转换(NAT / NAPT),以及用 ...
- ios-时间换算
经常会遇到时间转换的,在此收藏一个时间换算的方法〜 #pragma mark 时间换算 + (NSString *)setcreateTime:(NSString *)str { //yyyy-MM- ...
- 大数据量下的SQL Server数据库自身优化
原文: http://www.d1net.com/bigdata/news/284983.html 1.1:增加次数据文件 从SQL SERVER 2005开始,数据库不默认生成NDF数据文件,一般情 ...
- Actifio快照池(snapshot pool)空间占用说明
快照池是什么? 快照池是根据定义的SLA(Service Level Agreement)来保存应用数据各时间点的黄金副本空间. 快照池空间的消耗 快照池空间由三种不同类型的虚拟磁盘使用: Stagi ...
- 修改windows7 的管理员密码
某天,公司财务同事的电脑出现了一个相当奇葩的现象,有些程序不能用了,经过查看,发现本是管理员的账户变得只有一个users用户组了 造成程序在运行时,无权限修改一些文件,造成程序无法启动 my god, ...
- Linux csplit命令详解
Linux csplit命令 Linux csplit命令用于分割文件.拆解文件主要是split和csplit命令,如果说split是按大小来拆分的话,那么csplit则可按匹配来拆分: 将文件依照指 ...
- Oracle数据csv导入
打开工具,在tool下面有个Text Importer 先选择Data from textfile选项卡 然后选择 Open data file ,打开要导入的文件 1\ 2\ 再先选择Data to ...
- 通过localhost访问和通过IP地址访问页面CSS样式不一样
在开发ICT项目管理系统时,发现在开发环境下看到的页面和在部署环境下看到的页面不一样.开发环境下看到的页面比较舒服,部署后看到的页面比较生涩.究其原因,发现地址栏里面一个是localhost,一个是I ...
- bat文件与Vbs文件常用操作(获取用户输入,执行VBS文件)
bat文件: set /P StrInput="输入数字:" echo 输入的数字为%StrInput% set /P Flg="是否执行(y/n):" IF ...