一、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. 构建之法 chapter1 心得

    阅读完了<构建之法>第一章后,觉得我们平时使用的软件并不是自己想象中的那样简单,用的时候是觉得很方便,但从来没有考虑过一个软件的背后需要一个团队多少的付出才能换来一个获得用户频频好评的软件 ...

  2. js判断页面在pc端打开还是移动端打开

    js判断页面在pc端打开还是移动端打开,分别跳转不同的index.html window.addEventListener('load', function() { // true为手机,false为 ...

  3. 学习笔记DL003:神经网络第二、三次浪潮,数据量、模型规模,精度、复杂度,对现实世界冲击

    神经科学,依靠单一深度学习算法解决不同任务.视觉信号传送到听觉区域,大脑听学习处理区域学会“看”(Von Melchner et al., 2000).计算单元互相作用变智能.新认知机(Fukushi ...

  4. Java(原码、反码、补码和计算机存储格式)

    原码:将一个整数,转换成二进制,就是其原码.如单字节的5的原码为:0000 0101:-5的原码为1000 0101. 反码:正数的反码就是其原码:负数的反码是将原码中,除符号位以外,每一位取反.如单 ...

  5. vue中父组件给子组件额外添加参数

    1 子组件: this.$emit('callbackone',item.parentId) 2 父组件: @callbackone="callbackone($event,index)&q ...

  6. c# 纯代码调用 webservice

    public static class RequestHelper { public class RequestResult { public RequestResult(bool requestRe ...

  7. Oracle数据csv导入

    打开工具,在tool下面有个Text Importer 先选择Data from textfile选项卡 然后选择 Open data file ,打开要导入的文件 1\ 2\ 再先选择Data to ...

  8. RK3399 友善NanoPC-T4开发板使用sysfs方法控制status LED状态灯-【申嵌视频-RK3399篇】

    实验1:sysfs 操作方法控制NanoPC-T4开发板上LED灯 (status LED状态灯:GPIO0_B5/LED1_OUT)root@NanoPC-T4: cd /sys/class/led ...

  9. VirtualApk 插件入门小试

    1 官方资料 滴滴开源Android插件方案:VirtualAPK 2 宿主App集成方法 (1)在整个工程的build.gradle中添加依赖 dependencies { classpath 'c ...

  10. php_screw安装,使用

    安装步骤:1. 下载源码:wget http://nchc.dl.sourceforge.net/project/php-screw/php-screw/1.5/php_screw-1.5.tar.g ...