Rabbit使用CorrelationId进行可靠性消息回调
先放一张使用CorrelationId相关ID进行消息回调处理的流程图

- 客户端启动时,它将创建一个匿名回调队列
- 对于 RPC 请求,客户端发送一条消息,该消息具有两个属性: reply_to(设置为回调队列)和 correlation_id(设置为每个请求的唯一值)
- 该请求被发送到 rpc_queue 队列
- RPC 工作程序等待该队列上的请求,出现请求时,它将使用 reply_to 字段中的队列来完成工作,并将消息和结果发送回客户端
- 客户端等待回调队列上的数据,出现消息时,它将检查 correlation_id 属性。 如果它与请求中的值匹配,则将响应返回给应用程序(TODO)
发送回调
public void SendCallback<T>(string topic, T value, Action<byte[]> callback, byte priority = 1)
{
EnsureDeclare(topic);
var replyQueue = _model.QueueDeclare().QueueName;
var props = _model.CreateBasicProperties();
props.Priority = priority;
props.ReplyTo = replyQueue;
var correlationId = Guid.NewGuid().ToString("N");
props.CorrelationId = correlationId; //发布消息
_model.BasicPublish(_exchange, topic, props, value.GetBuf()); //创建消费者用于消息回调
var callbackConsumer = new EventingBasicConsumer(_model);
_model.BasicConsume(queue: replyQueue, autoAck: true, consumer: callbackConsumer); callbackConsumer.Received += (model, ea) =>
{
if (ea.BasicProperties.CorrelationId == correlationId)
callback(ea.Body);
};
}
消息接收,在接受消息后,通过ReplyTo来进行消息回执
public void SetReceiveCallback(string topic, Action<byte[], IBasicProperties> received)
{
EnsureDeclare(topic);
var consumer = new EventingBasicConsumer(_model);
consumer.Received += (model, ea) =>
{
var properties = ea.BasicProperties;
var replyProerties = _model.CreateBasicProperties();
replyProerties.CorrelationId = properties.CorrelationId;
replyProerties.ReplyTo = properties.ReplyTo;
received(ea.Body, replyProerties);
_model.BasicAck(ea.DeliveryTag, false);
};
_model.BasicConsume(topic, false, consumer);
}
单元测试代码
[Order(1)]
public class RabbitCallbackTest
{
[Fact, Order(1)]
public void ServerCallback()
{
_rabbitSvr = new Aster.Itms.Core.Data.Provider.Rabbit(new Connection()
{
Ip = "localhost",
Port = 5672,
User = "guest",
Password = "guest"
}, ""); _rabbitSvr.SetReceiveCallback("topic", ServerReceiveCommand);
} private static volatile Aster.Itms.Core.Data.Provider.Rabbit _rabbitSvr;
[Fact, Order(2)]
public void ClientCallback()
{
var _rabbitSvr = new Aster.Itms.Core.Data.Provider.Rabbit(new Connection()
{
Ip = "localhost",
Port = 5672,
User = "guest",
Password = "guest"
}, ""); string val = $"发送消息{Guid.NewGuid().ToString("N")}"; _rabbitSvr.SendCallback<string>("topic", val, ClientReceiveCommand, 1);
} private static void ClientReceiveCommand(byte[] body)
{
var result = body.To<string>(); //拿到结果再发送回去 Console.WriteLine($"接收服务端返回消息:{result}"); Assert.NotEmpty(result);
} private static void ServerReceiveCommand(byte[] body, IBasicProperties replyProps)
{
var result = body.To<string>(); Assert.NotEmpty(result); Console.WriteLine($"服务端接收:{result},CorrelationId:{replyProps.CorrelationId}"); int.TryParse(result, out int newResult); if (!string.IsNullOrEmpty(replyProps.ReplyTo))
_rabbitSvr.Send(replyProps.ReplyTo, $"{Convert.ToInt32(newResult) + 1000}", replyProps);
}
}
Rabbit使用CorrelationId进行可靠性消息回调的更多相关文章
- 2.RabbitMQ 的可靠性消息的发送
本篇包含 1. RabbitMQ 的可靠性消息的发送 2. RabbitMQ 集群的原理与高可用架构的搭建 3. RabbitMQ 的实践经验 上篇包含 1.MQ 的本质,MQ 的作用 2.R ...
- 终于懂了:Delphi消息的Result域出现的原因——要代替回调函数的返回值!(MakeObjectInstance不会帮助处理(接收)消息回调函数的返回值)
MakeObjectInstance应该不会帮助处理(接收)消息回调函数的返回值,可是有时候又确实需要这个返回值,这可怎么办呢?我是看到这段文字的时候,想到这个问题的: 当WM_PAINT不是由Inv ...
- Rabbit MQ 怎么保证可靠性、幂等性、消费顺序?
RabbitMQ如何保证消息的可靠性 RabbitMQ消息丢失的三种情况 生产者弄丢消息时的解决方法 方法一:生产者在发送数据之前开启RabbitMQ的事务(采用该种方法由于事务机制,会导致吞吐量下降 ...
- Rabbit mq订阅方式获取消息并可设置持久化
Rabbit 通过方式获取消息:订阅方式事实上是向queue注冊consumer,通过rpc向queue server发送注冊consumer的消息.rabbitMQ Server在收到消息后,依据消 ...
- 【mq读书笔记】客户端处理消息(回调提交到异步业务线程池,pullRequest重新入队)
看一下客户端收到消息后的处理: MQClientAPIImpl#processPullResponse private PullResult processPullResponse( final Re ...
- 理解Storm可靠性消息
看过一些别人写的, 感觉有些东西没太说清楚,个人主要以源代码跟踪,参考个人理解讲述,有错误请指正. 1基本名词 1.1 Tuple: 消息传递的基本单位.很多文章中介绍都是这么说的, 个人觉得应该更详 ...
- Spring Boot and Rabbit MQ 异常的时候消息的状态
我们有一个处理消息的方法. 在处理消息的时候出现了异常,那出现异常后这个消息会怎么处理呢. 根据我们的实际情况的观察,如果出现了异常. 但是你没有捕获或者处理异常,这个消息会一直存在,并且你的系统会持 ...
- 专门用于消息回调窗口的窗口标识HWND_MESSAGE(创建一个非可视、没有z-order的窗口)
HWND_MESSAGE Message-Only Windows A message-only window enables you to send and receive messages. It ...
- Rabbit MQ 消息确认和持久化机制
一:确认种类 RabbitMQ的消息确认有两种.一种是消息发送确认,用来确认生产者将消息发送给交换器,交换器传递给队列的过程中消息是否成功投递.发送确认分为两步,一是确认是否到达交换器,二是确认是否到 ...
- RabbitMQ消息可靠性分析
消息中间件的可靠性是指对消息不丢失的保障程度:而消息中间件的可用性是指无故障运行的时间百分比,通常用几个 9 来衡量.不存在绝对的可靠性只能尽量趋向完美.并且通常可靠性也意味着影响性能和付出更大的成本 ...
随机推荐
- echarts使用transform缩放后导致图标模糊
echarts使用transform缩放后导致图标模糊 --的解决办法 当使用了transform: scale(x,y)缩放后致使echarts图表模糊.怎么解决这个问题呢? 第一种解决办法:将ca ...
- 使用boot.iso镜像安装Oracle Linux 8
本文记录使用boot.iso镜像安装Oracle Linux 8. 镜像下载 Oracle Linux 8 boot镜像可以从这里下载. 安装 Oracle Linux 8 boot镜像安装系统跟使用 ...
- win10家庭版禁用更新
前言 2020年初因为疫情在家远程办公,而我老家没有电脑,先后向两位大学生借了两台电脑来办公,发现一个现象:他们的电脑系统都是家庭版,也就是刚买电脑时安装的win10家庭版.也问了其它几位计算机专业的 ...
- npm旧淘宝镜像过期,更换新淘宝镜像
1. 清空缓存 npm cache clean --force 2.设置新淘宝镜像 npm config set registry https://registry.npmmirror.com/ 3. ...
- .NetCore 三种生命周期注入方式
.NetCore彻底诠释了"万物皆可注入"这句话的含义,在.NetCore中到处可见注入的使用.因此core中也提供了三种注入方式的使用,分别是: AddTransient:每次请 ...
- CF1916E Happy Life in University 题解
题目: CF1916E Happy Life in University 链接: 洛谷 或者 CF 前置知识点: 线段树与HH的项链 先简单回顾下HH的项链这题怎么做的吧.先去掉莫队算法,因为这个不是 ...
- Linux RDP 会话中无法打开VSCode 解决办法
github issue: VS Code "and still" won't open in a Linux xrdp session Workaround- Linux RDP ...
- static_cast, dynamic_cast与reinterpret_cast的区别
在C++中,static_cast, dynamic_cast和reinterpret_cast都可用于类型转换,它们在具体使用时有什么区别?此外,更为重要的是,为什么不推荐使用强制类型转换? 1. ...
- 【题解】P5461 赦免战俘
一.题目 现有 \(2^n\times2^n\ (n≤10)\) 名作弊者站成一个正方形方阵等候 kkksc03 的发落.kkksc03 决定赦免一些作弊者.他将正方形矩阵均分为 4 个更小的正方形矩 ...
- 探索Web API SpeechSynthesis:给你的网页增添声音
Web API SpeechSynthesis是一项强大的浏览器功能,它允许开发者将文本转换为语音,并通过浏览器播放出来.本文将深入探讨SpeechSynthesis的控制接口,包括其功能.用法和一个 ...