一、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—确认队列和响应队列的更多相关文章

  1. PHP电商订单自动确认收货redis队列

    一.场景 之前做的电商平台,用户在收到货之后,大部分都不会主动的点击确认收货,导致给商家结款的时候,商家各种投诉,于是就根据需求,要做一个订单在发货之后的x天自动确认收货.所谓的订单自动确认收货,就是 ...

  2. 三次握手 四次握手 原因分析 TCP 半连接队列 全连接队列

    小结 1. 三次握手的原因:保证双方收和发消息功能正常: [生活模型] "请问能听见吗""我能听见你的声音,你能听见我的声音吗" [原理]A先对B:你在么?我在 ...

  3. RabbitMQ使用 prefetch_count优化队列的消费,使用死信队列和延迟队列实现消息的定时重试,golang版本

    RabbitMQ 的优化 channel prefetch Count 死信队列 什么是死信队列 使用场景 代码实现 延迟队列 什么是延迟队列 使用场景 实现延迟队列的方式 Queue TTL Mes ...

  4. Java多线程:队列与阻塞队列

    1. 什么是阻塞队列 阻塞队列(BlockingQueue)是 Java 5 并发新特性中的内容,阻塞队列的接口是 java.util.concurrent.BlockingQueue,它提供了两个附 ...

  5. 为什么使用消息队列?消息队列有什么优点和缺点?Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么优点和缺点?

    面试题 为什么使用消息队列? 消息队列有什么优点和缺点? Kafka.ActiveMQ.RabbitMQ.RocketMQ 都有什么区别,以及适合哪些场景? 面试官心理分析 其实面试官主要是想看看: ...

  6. RabbitMQ六种队列模式-简单队列模式

    前言 RabbitMQ六种队列模式-简单队列 [本文]RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主 ...

  7. RabbitMQ从零到集群高可用(.NetCore5.0) - 死信队列,延时队列

    系列文章: RabbitMQ从零到集群高可用(.NetCore5.0) - RabbitMQ简介和六种工作模式详解 RabbitMQ从零到集群高可用(.NetCore5.0) - 死信队列,延时队列 ...

  8. RabbitMQ 入门系列:10、扩展内容:延时队列:延时队列插件及其有限的适用场景(系列大结局)。

    系列目录 RabbitMQ 入门系列:1.MQ的应用场景的选择与RabbitMQ安装. RabbitMQ 入门系列:2.基础含义:链接.通道.队列.交换机. RabbitMQ 入门系列:3.基础含义: ...

  9. C ~ 链式队列与循环队列

          此处的链式与循环队列可以应用于BFS和树的层序遍历.下面是对其结构和基本操作的程序描述. 1.循环队列 解决循环队列的队空和队满的方法: [1].增加一个参数count,用来记录数组中当前 ...

随机推荐

  1. js···元素的属性

    Div.attributes 是所有标签属性构成的数据集合 Div.classList 是所有class名构成的数组集合 在classList的原型链上看以看到add()和remove(). clie ...

  2. MySQL Hardware--NUMA与MySQL

    MUMA架构 在单实例的MySQL服务器上,通过会为MySQL的Buffer Pool分配50%至70%甚至更高的内存,让MySQL 服务会尽可能多地占用系统资源.在基于NUMA系统中,内存被分配到各 ...

  3. C#中的参数和调用方式(可选参数、具名参数、可空参数)

    具名参数 和 可选参数 是 C# framework 4.0 出来的新特性. 一. 常规方法定义及调用 public void Demo1(string x, int y) { //do someth ...

  4. Linux下 USB设备驱动分析(原创)

    之前做过STM32的usb HID复合设备,闲来看看linux下USB设备驱动是怎么一回事, 参考资料基于韦东山JZ2440开发板,以下,有错误欢迎指出. 1.准备知识 1.1USB相关概念: USB ...

  5. 机器学习实战ch04 关于python版本所支持的文本格式问题

    函数定义中: def spamTest(): docList=[]; classList = []; fullText =[] for i in range(1,26):# print('cycle ...

  6. keepalived+mysql主从环境,keepalived返回值是RST,需求解决方法?

    环境描述: mysql版本5.6.37    keepalived-1.2.19    系统centos 7:3.10.0-514.26.2.el7    web是:windows  server 2 ...

  7. C++标准模板类库(STL)之queue初步

    1,STL里有些什么? 包括三个内容:容器.迭代器.算法. 2,容器有哪些? 有stack, vector, queue, deque, list, set, multiset, map, multi ...

  8. tomcat守护相关

    tomcat守护相关(centos7) 今天在部署自己的服务到CentOS7服务器上tomcat中时,担心服务宕机想守护一下服务程序,于是现在网上找了一个用while写的循环守护脚本,后来发现这种方式 ...

  9. Python【每日一问】10

    问:请解释一下迭代器 答:可以被 __next__() 函数调用并不断返回下一个值的对象称为迭代器:Iterator

  10. 2018.7.3 lnmp一键安装包无人值守版本 php7.2 + nginx1.14.0 + mariadb5.5 + centos7.1(1503) 环境搭建 + Thinkphp5.1.7 配置

    给自己练习用的,整个过程追求一个简单粗暴,没有配置虚拟主机,现在记录一下过程. 1. 进入到lnmp解压缩后的文件夹conf/rewrite,把thinkphp.conf复制一份到/usr/local ...