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 来衡量.不存在绝对的可靠性只能尽量趋向完美.并且通常可靠性也意味着影响性能和付出更大的成本 ...
随机推荐
- 记录一次RPC服务有损上线的分析过程
1. 问题背景 某应用在启动完提供JSF服务后,短时间内出现了大量的空指针异常. 分析日志,发现是服务依赖的藏经阁配置数据未加载完成导致.即所谓的有损上线或者是直接发布,当应用启动时,service还 ...
- 一种读取亿级doris数据库的方法
工作中,常常需要将线上doris同步至集市.读取doris数据同读取常规mysql基本相同.如果数据行小于千万,比较简单的方式直接单节点连接.读取和存储.Python示例如下: def get_dat ...
- Istio安装和部署
Istio的版本对k8s的版本是有要求的,不兼容的版本会引发一些隐蔽的错误,安装前先参考下图 版本 目前支持 发行日期 停止维护 支持的 Kubernetes 版本 未测试,可能支持的 Kuberne ...
- css 宽度分离原则
我们想设计一个w=180px:h=100px的div; .demo1 { width: 180px; height: 100px; background: pink; padding: 10px; b ...
- vue混入mixin
<div id="app"> --{{nick11}} </div> <script> // 全局混入 不需要注册 var m1 = Vue.m ...
- 【小测试】读取*.proto文件,再读取service中method的注释
想要在proto3中定义service,及其service的method.然后在method后面加上特殊注释,通过这个特殊注释来动态生成代码. 下面是测试代码: import ( "gith ...
- Protocol Buffer命名空间冲突
原文在这里. 什么是Protocol Buffer命名空间冲突? 所有链接到Go二进制文件的Protocol Buffer声明都被插入到一个全局注册表中. 每个Protocol Buffer声明(例如 ...
- IDM(最佳的Windows下载工具)
如果你是一名互联网"老司机",那么一定听过「IDM」这款下载工具的大名!它的全名叫做 Internet Download Manager (互联网下载管理器),缩写就是 IDM. ...
- 3.5 Windows驱动开发:应用层与内核层内存映射
在上一篇博文<内核通过PEB得到进程参数>中我们通过使用KeStackAttachProcess附加进程的方式得到了该进程的PEB结构信息,本篇文章同样需要使用进程附加功能,但这次我们将实 ...
- C++ Boost库 操作日期与时间
Boost库中默认针对日期与时间的操作库分为,timer,progress_timer,date_time这几类,如下是一些常用的使用方法总结. timer库 #include <iostrea ...