8.RabbitMQ系列之RPC
1. RPC
Remote Procedure Call:远程过程调用,一次远程过程调用的流程即客户端发送一个请求到服务端,服务端根据请求信息进行处理后返回响应信息,客户端收到响应信息后结束
2. Client interface客户端接口
为了说明如何使用RPC服务,我们将把“发送方”和“接收方”更改为“客户端”和“服务器”。当我们调用服务时,我们将得到我们对应的斐波那契值
Integer response = (Integer) template.convertSendAndReceive
(exchange.getName(), "rpc", 5);
System.out.println(" [.] Got '" + response + "'");
3. Callback queue回调队列
一般来说,通过RabbitMQ执行RPC很容易。客户端发送请求消息,服务器进行回复。为了接收响应,我们需要随请求一起发送“回调”队列地址。当我们使用上述convertSendAndReceive()方法时,Spring AMQP的RabbitTemplate为我们处理回调队列。使用RabbitTemplate时,无需执行任何其他设置
Message properties消息属性
- deliveryMode:将消息标记为持久(值为2)或瞬态(任何其他值)
- contentType: 用于描述编码的mime-type。例如,对于经常使用的JSON编码,将此属性设置为:application/JSON是一种很好的做法
- replyTo:常用于命名回调队列
- correlationId: 用于将RPC响应与请求关联
4. Correlation Id关联ID
Spring AMQP允许您关注正在使用的消息方式,并隐藏支持此方式所需的消息管道的详细信息。例如,本机客户端通常会为每个RPC请求创建一个回调队列。这效率很低,所以另一种方法是为每个客户端创建一个回调队列
这引发了一个新问题,在该队列中收到响应后,不清楚响应属于哪个请求。此时将使用correlationId属性。Spring AMQP自动为每个请求设置唯一值。此外,它还处理拥有正确correlationID的响应
Spring AMQP使RPC样式更容易的一个原因是,有时您可能希望忽略回调队列中的未知消息,而不是由于错误而失败。这是由于服务器端可能存在竞争条件。虽然不太可能,但RPC服务器可能会在向我们发送应答之后,但在发送请求的确认消息之前死亡。如果发生这种情况,重新启动的RPC服务器将再次处理该请求。Spring AMQP客户端优雅地处理重复的响应,理想情况下RPC应该是幂等的
4. 总结

RPC工作流程如下:
- RpcConfig新建一个直连交换器rpc并绑定队列
- 客户端调用convertSendAndReceive方法,设置exchange、routing key、message
- 请求并发送至队列rpc.requests
- 服务端监听队列中的客户端请求,请求一旦进入队列,服务端开始工作并使用队列的replyTo字段进行响应,
- 客户端等待回调队列中消息,当消息到达,其核查correlationId字段,如果匹配,则返回响应消息给应用。这在RabbitTemplate自动实现
5. 完整代码
@Configuration
public class RpcConfig {
@Bean
public DirectExchange rpc() {
return new DirectExchange("rpc");
}
private static class ServerConfig {
@Bean
public Queue rpcQueue() {
return new Queue("rpc.requests");
}
@Bean
public Binding binding(DirectExchange rpc,
Queue rpcQueue) {
return BindingBuilder.bind(rpcQueue)
.to(rpc)
.with("rpc");
}
}
}
@Component
public class RpcClient {
private RabbitTemplate rabbitTemplate;
public RpcClient(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}
public void send() {
System.out.println(" [客户端] 发送请求10");
Integer response = (Integer) rabbitTemplate.convertSendAndReceive("rpc", "rpc", 10);
System.out.println(" [客户端] 收到响应 " + response + "");
}
}
@Component
public class RpcServer {
@RabbitListener(queues = "rpc.requests")
public int fibonacci(int n) {
System.out.println(" [服务端] 收到请求" + n);
int result = fib(n);
System.out.println(" [服务端] 响应请求 " + result);
return result;
}
public int fib(int n) {
return n == 0 ? 0 : n == 1 ? 1 : (fib(n - 1) + fib(n - 2));
}
}
@SpringBootTest
public class RabbitTest {
@Autowired
private RpcClient rpcClient;
@Test
public void testRpc() {
rpcClient.send();
}

8.RabbitMQ系列之RPC的更多相关文章
- RabbitMQ系列教程之六:远程过程调用(RPC)
远程过程调用(Remote Proceddure call[RPC])(本实例都是使用的Net的客户端,使用C#编写) 在第二个教程中,我们学习了如何使用工作队列在多个工作实例之间分配耗时的任务. ...
- RabbitMQ系列教程之六:远程过程调用(RPC)(转载)
RabbitMQ系列教程之六:远程过程调用(RPC) 远程过程调用(Remote Proceddure call[RPC]) (本实例都是使用的Net的客户端,使用C#编写) 在第二个教程中,我们学习 ...
- Python操作rabbitmq系列(六):进行RPC调用
此刻,我们已经进入第6章,是官方的最后一个环节,但是,并非本系列的最后一个环节.因为在实战中还有一些经验教训,并没体现出来.由于马上要给同事没培训celery了.我也来不及写太多.等后面,我们再慢慢补 ...
- rabbitmq系列五 之远程过程调用(RPC)
1.远程过程调用(RPC) 在第二篇教程中我们介绍了如何使用工作队列(work queue)在多个工作者(woker)中间分发耗时的任务. 可是如果我们需要将一个函数运行在远程计算机上并且等待从那儿获 ...
- 在Node.js中使用RabbitMQ系列二 任务队列
在上一篇文章在Node.js中使用RabbitMQ系列一 Hello world我有使用一个任务队列,不过当时的场景是将消息发送给一个消费者,本篇文章我将讨论有多个消费者的场景. 其实,任务队列最核心 ...
- RabbitMQ中的RPC实现
1.RPC简述 RPC,Remote Procedure Call 远程过程调用.通俗讲,两段程序不在同一个内存空间,无法直接通过方法名调用,就需要通过网络通信方式调用.对于RabbitMQ,本身就是 ...
- RabbitMQ系列(四)RabbitMQ事务和Confirm发送方消息确认——深入解读
RabbitMQ事务和Confirm发送方消息确认--深入解读 RabbitMQ系列文章 RabbitMQ在Ubuntu上的环境搭建 深入了解RabbitMQ工作原理及简单使用 RabbitMQ交换器 ...
- RabbitMQ系列(三)RabbitMQ交换器Exchange介绍与实践
RabbitMQ交换器Exchange介绍与实践 RabbitMQ系列文章 RabbitMQ在Ubuntu上的环境搭建 深入了解RabbitMQ工作原理及简单使用 RabbitMQ交换器Exchang ...
- RabbitMQ系列(二)深入了解RabbitMQ工作原理及简单使用
深入了解RabbitMQ工作原理及简单使用 RabbitMQ系列文章 RabbitMQ在Ubuntu上的环境搭建 深入了解RabbitMQ工作原理及简单使用 RabbitMQ交换器Exchange介绍 ...
随机推荐
- WebView2 通过 PuppeteerSharp 实现爬取 王者 壁纸 (案例版)
此案例是<.Net WebView2 项目,实现 嵌入 WEB 页面 Chromium内核>文的续集. 主要是针对WebView2的一些微软自己封装的不熟悉的API,有一些人已经对 Pup ...
- 开源深度思考 - In Community We Trust
作者 | 黄东旭,PingCAP 联合创始人&CTO 出品 | CSDN(ID:CSDNnews) 业界一直流传着黄东旭的传说:小学三年级开始写代码,四五年级学习C语言,初中毕业时,已经能够用 ...
- jbd2的死锁分析
已经运行多年的jbd2,它还是死锁了 背景:这个是在centos7的环境上复现的,内核版本为3.10.0-957.27.2.el7 下面列一下我们是怎么排查并解这个问题的. 一.故障现象 oppo云内 ...
- 上传代码到GitHub仓库
上传代码到GitHub仓库 准备工作 意思是自从 21 年 8 月 13 后不再支持用户名密码的方式验证了,需要创建个人访问令牌(personal access token). 这里就不多说了 Git ...
- mybatisplus入门
一.maven项目文件 点击查看代码 <dependency> <groupId>org.springframework.boot</groupId> <ar ...
- AI 音辨世界:艺术小白的我,靠这个AI模型,速识音乐流派选择音乐 ⛵
作者:韩信子@ShowMeAI 数据分析实战系列:https://www.showmeai.tech/tutorials/40 机器学习实战系列:https://www.showmeai.tech/t ...
- 学习ASP.NET Core Blazor编程系列一——综述
一.NET 6概述 .NET 6 是微软统一.Net Core与.Net Framework 两大框架的第二个版本,微软在 .NET 5 中开始进行这两大框架的统一之路. .NET 6 将作为长期支持 ...
- FusionCopmpute之CNA,VRM虚拟机安装
CNA和VRM安装步骤一样,需要修改的只有IP 按步骤创建 修改自己虚拟机想要存放的位置 需要把自己网络同样配置为仅主机(提前配好) 自己也可以修改至200G 虚拟机只是用多少取多少 CNA可以设置为 ...
- 【设计模式】Java设计模式 - 反射机制
[设计模式]Java设计模式 - 反射机制 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 目录 [设计模式]Java设计模式 - 反射 ...
- PLSQL 与 PLPGSQL
KingbaseES 为了更好地适应用户的oracle 应用,实现了对 plsql 的支持,用户可以根据需要使用 plsql 或 plpgsql. 以下简要介绍下二者的差异 一.格式差异 1.plpg ...