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 来衡量.不存在绝对的可靠性只能尽量趋向完美.并且通常可靠性也意味着影响性能和付出更大的成本 ... 
随机推荐
- Spring 应用合并之路(一):摸石头过河 | 京东云技术团队
			公司在推进降本增效,在尝多种手段之后,发现应用太多,每个应用都做跨机房容灾部署,则最少需要 4 台机器(称为容器更合适).那么,将相近应用做一个合并,减少维护项目,提高机器利用率就是一个可选方案. 经 ... 
- 如何写RN样式   如何写RN组件  如何满屏   如何使用变量
			app.js 文本水平居中了哈 控制文本的大小 字体颜色等 只有在文本元素上去控制哈 import React from 'react'; import {View, Text, StyleSheet ... 
- 小白学k8s(2)理解flannel网络
			理解flannel网络 简介 Kubernetes中的网络 flannel 总结 参考 理解flannel网络 简介 Flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务,简 ... 
- Java并发(八)----使用线程避免cpu占用100%
			1.sleep 实现 在没有利用 cpu 来计算时,不要让 while(true) 空转浪费 cpu,这时可以使用 yield 或 sleep 来让出 cpu 的使用权给其他程序 while(true ... 
- JS Leetcode 179. 最大数 题解分析,sort a-b与b-a的区别,sort排序原理解析
			壹 ❀ 引 今天的题目来自LeetCode179. 最大数,题目描述如下: 给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数. 注意:输出结果可能非常大,所以你 ... 
- JS leetcode 拥有最多糖果的孩子 题解分析,六一快乐。
			壹 ❀ 引 今天是六一儿童节,leetcode的每日一题也特别可爱,那么今天我们来解决一道与糖果有关的问题,题目来源1431. 拥有最多糖果的孩子,题目描述如下: 给你一个数组 candies 和一个 ... 
- 【译】IEEE白皮书 6G 太赫兹技术的基本原理 2023版
			第一章 简介 太赫兹波是介于微波和光波之间的光谱区域,频率从 0.1THz ~ 10THz 之间,波长在 3mm ~ 30μm 之间.提供大块连续的频带范围以满足对 Tbit/s 内极高数据传输速率的 ... 
- Java I/O 教程(十二) OutputStreamWriter和InputStreamReader
			OutputStreamWriter类 OutputStreamWriter是字符流到字节流的桥梁,字符写入其中后被指定字符集成字节. 字符集可自定义,或使用平台默认字符集. 推荐使用Buffered ... 
- EXPLAIN命令
			EXPLAIN命令 除了以SELECT开头的查询语句,其余的DELETE.INSERT.REPLACE以及UPDATE语句前边都可以加上EXPLAIN这个词儿,用来查看这些语句的执行计划 Ty ... 
- MinGW 和 MSVC
			在 Winodws 上编译通常会用到这两种工具链 MinGW(Minimalist GNU for Windows) 通常用于跨平台开发,可以编译出在 Windows 系统上运行的 .exe 程序 M ... 
