原文:RabbitMQ入门教程(八):远程过程调用RPC

版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。

分享一个朋友的人工智能教程。比较通俗易懂,风趣幽默,感兴趣的朋友可以去看看。

简介

远程过程调用(RPC): 客户端发送一个请求到远程服务器上,远程服务器接收请求并处理结果,将结果响应给客户端,这个过程被称为远程过程调用。

RPC涉及到的基本知识:

  • 关于队列:整个过程会设计到两个队列一个是专门保存请求的队列,一般名字被称为rpc_queue,另一个队列被称为响应队列,专门用于保存服务器处理的响应结果,这个队列的名字是随机生成的字符串。

  • 关于消息的基本属性BasicProperties:回复(replyTo):是响应队列的名字,当服务器接收请求并处理好结果,服务器需要知道将响应的信息发送到哪个队列中;关联id(correlationId):是一个UUID值,发消息的时候会带上这个值,该值在客户端接收响应时用于判断接收到的响应消息是否是自己发出请求对应的响应; 客户端在发送请求时需要带上replyTo和correlationId两个属性。

  • 其他属性:contentType:内容类型,用来描述编码的MIME类型。例如,经常使用JSON编码是将此属性设置为一个很好的做法:application/json,在rpc中该属性不是必须的

RPC的过程描述:

  • 客户端首先将请求消息发送到请求队列,在发送请求时需要指定replyTo和correlationId两个值;

  • 服务端需要预先订阅请求队列(rpc_queue),以便服务器端能随时接受到请求消息,当服务端接收到请求消息时对请求进行处理,将处理结果发送到响应队列(随机队列)中

  • 客户端还要预先订阅响应队列(随机队列),以便当服务器发送响应消息到响应队列中,客户端能及时收到响应结果,服务器在将响应发送到响应队列中还要指定correlationId值(类似于唯一标记当前的请求),这样当客户端从响应队列中接收到消息时就可以通过correlationId的值是否和发送请求的关联id值是否相同,如果相同就证明这个响应结果就是这个请求对应的响应结果。注意这个预先订阅响应队列的步骤需要在客户端中完成,最好在客户端发送请求消息前就完成。

客户端Client

@Test
public void client() throws Exception{
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(AMQP.PROTOCOL.PORT);
factory.setUsername("mengday");
factory.setPassword("mengday"); Connection connection = factory.newConnection();
Channel channel = connection.createChannel(); // 预先定义响应的结果,即预先订阅响应结果的队列,先订阅响应队列,再发送消息到请求队列
String reyply_to_queue = channel.queueDeclare().getQueue();
final String correlationId = UUID.randomUUID().toString();
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
if (properties.getCorrelationId().equals(correlationId)) {
String message = new String(body, "UTF-8");
System.out.println("已接收到服务器的响应结果:" + message);
}
}
};
channel.basicConsume(reyply_to_queue, true, consumer); // 将消息发送到请求队列中
String rpc_queuqu = "rpc_queue";
String message = "Hello RabbitMQ";
AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder().correlationId(correlationId).replyTo(reyply_to_queue).build();
channel.basicPublish("", rpc_queuqu, properties, message.getBytes("UTF-8"));
System.out.println("已发出请求请求消息:" + message);
Thread.sleep(100000);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

服务器端Server

@Test
public void server() throws Exception{
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setPort(AMQP.PROTOCOL.PORT);
factory.setUsername("mengday");
factory.setPassword("mengday"); Connection connection = factory.newConnection();
final Channel channel = connection.createChannel();
String rpc_queuqu = "rpc_queue";
channel.queueDeclare(rpc_queuqu, false, false, false, null);
channel.basicQos(1); Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "UTF-8");
System.out.println("服务端:已接收到请求消息:" + message);
// 服务器端接收到消息并处理消息
String response = "{'code': 200, 'data': '" + message+ "'}"; // 将消息发布到reply_to响应队列中
AMQP.BasicProperties replyProperties = new AMQP.BasicProperties.Builder().
correlationId(properties.getCorrelationId()).build();
String replyTo = properties.getReplyTo();
channel.basicPublish("", replyTo, replyProperties, response.getBytes("UTF-8"));
System.out.println("服务端:请求已处理完毕,响应结果" + response + "已发送到响应队列中");
// 手动应答
channel.basicAck(envelope.getDeliveryTag(), false);
}
}; // 手动应答模式
channel.basicConsume(rpc_queuqu, false, consumer); System.out.println("服务端:已订阅请求队列(rpc_queue), 开始等待接收请求消息...");
Thread.sleep(100000);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

运行效果

先运行服务端,再运行客户端


分享一个朋友的人工智能教程。比较通俗易懂,风趣幽默,感兴趣的朋友可以去看看。

我的微信公众号:

RabbitMQ入门教程(八):远程过程调用RPC的更多相关文章

  1. python中RabbitMQ的使用(远程过程调用RPC)

    在RabbitMQ消息队列中,往往接收者.发送者不止是一个身份.例如接接收者收到消息并且需要返回给发送者. 此时接收者.发送者的身份不再固定! 我们来模拟该情形: 假设有客户端client,服务端se ...

  2. RabbitMQ九:远程过程调用RPC

    定义 RPC(Remote Procedure Call Protocol)——远程过程调用协议:它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.RPC协议假定某些传输协议 ...

  3. RabbitMQ 实现远程过程调用RPC

    RPC调用的顺序1. 在客户端初始化的时候,也就是SimpleRpcClient类初始化的时候,它会随机的创建一个callback队列,用于存放服务的返回值,这个队列是exclusive的.连接断开就 ...

  4. RabbitMQ入门教程(二):简介和基本概念

    原文:RabbitMQ入门教程(二):简介和基本概念 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn ...

  5. RabbitMQ入门教程 [转]

    1.引言 RabbitMQ--Rabbit Message Queue的简写,但不能仅仅理解其为消息队列,消息代理更合适.消息队列主要解决应用耦合,异步消息,流量削锋等问题.实现高性能,高可用,可伸缩 ...

  6. RabbitMQ入门教程(十二):消息确认Ack

    原文:RabbitMQ入门教程(十二):消息确认Ack 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csd ...

  7. RabbitMQ入门教程(九):首部交换机Headers

    原文:RabbitMQ入门教程(九):首部交换机Headers 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog ...

  8. RabbitMQ入门教程(四):工作队列(Work Queues)

    原文:RabbitMQ入门教程(四):工作队列(Work Queues) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https:/ ...

  9. RabbitMQ入门教程(三):Hello World

    原文:RabbitMQ入门教程(三):Hello World 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog. ...

随机推荐

  1. R_Studio(关联)对dvdtrans.csv数据进行关联规则分析

    dvdtrans.csv数据:该原始数据仅仅包含了两个字段(ID, Item) 用户ID,商品名称(共30条) #导入arules包 #install.packages("arules&qu ...

  2. LinkedList类源码浅析(二)

    1.上一节介绍了LinkedList的几个基本的方法,其他方法类似,就不一一介绍: 现在再来看一个删除的方法:remove(Object o) remove方法接受一个Object参数,这里需要对参数 ...

  3. Kotlin概述

    Kotlin 是一个基于 JVM 的新的编程语言,由 JetBrains 开发. Kotlin可以编译成Java字节码,也可以编译成JavaScript,方便在没有JVM的设备上运行. JetBrai ...

  4. 内网每一台电脑的外网ip是一样吗

    内网每一台电脑上网的IP地址是一样的,因为公网地址的稀缺性,所以内部上网是通过映射或者说叫端口复用将内部私有地址转换为公有地址进行上网的. 公有地址就是网关设备出口的地址,也可以说是路由器的出口地址, ...

  5. hash模块MD5加密

    MD5加密:获取32位加密字符串: 示例(MD5加密'123456')import hashlibhashObject=hashlib.md5(b'123456') #实例化,加密字符串不能直接加密, ...

  6. 阶段3 2.Spring_08.面向切面编程 AOP_9 spring基于注解的AOP配置

    复制依赖和改jar包方式 src下的都复制过来. 复制到新项目里了 bean.xml里面复制上面一行代码到下面.把aop改成context. 配置spring容器创建时要扫描的包 Service的配置 ...

  7. 阶段3 2.Spring_04.Spring的常用注解_4 由Component衍生的注解

    为什么要使用者三个注解 Controller:表现层 Service:业务层 Repository:持久层 在这里就是用Controller 运行也没问题 用Service Repository同样也 ...

  8. Python+requests+excel接口测试

    2018-06-14   17:00:13 环境准备: - Python 3.7 - requests库 - xlrd 1.创建Excel文件 2.读取Excel文件 import xlrd clas ...

  9. Tlbimp 生成c#互操作com组件dll;Tlbimp 生成.net互操作com组件dll

    Tlbimp 生成c#互操作com组件dll vs开发人员命令提示>进入到com组件目录>Tlbimp com.dll

  10. div 加滚动条 超过div宽度 自动换行 div居中

    一.div 中加滚动条 一. <div style=" overflow:scroll; width:400px; height:400px;”></div> 记住宽 ...