RabbitMQ中RPC的实现:客户端发送请求消息,服务端回复响应消息,为了接受响应response,客户端需要发送一个回调队列的地址来接受响应,每条消息在发送的时候会带上一个唯一的correlation_id,相应的服务端处理计算后会将结果返回到对应的correlation_id。

RPC调用流程:

当生产者启动时,它会创建一个匿名的独占回调队列,对于一个RPC请求,生产者发送一条具有两个属性的消息:reply_to(回调队列),correlation_id(每个请求的唯一值),请求被发送到rpc_queue队列,消费者等待该队列上的请求。当一个请求出现时,它会执行该任务,将带有结果的消息发送回生产者。生产者等待回调队列上的数据,当消息出现时,它检查相关ID属性,如果它与请求中的值匹配,则返回对应用程序的响应。

RabbitMQ斐波拉契计算的RPC,消费者实现:

"""
基于RabbitMQ实现RPC通信机制 --> 服务端
""" import pika
import uuid
from functools import lru_cache class RabbitServer(object):
def __init__(self):
self.conn = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost', port=5672)
)
self.channel = self.conn.channel() # 声明一个队列,并进行持久化,exclusive设置为false
self.channel.queue_declare(
exclusive=False, durable=True, queue='task_queue'
) # 声明一个exhange交换机,类型为topic
self.channel.exchange_declare(
exchange='logs_rpc', exchange_type='topic', durable=True
) # 将队列与交换机进行绑定
routing_keys = ['#'] # 接受所有的消息
for routing_key in routing_keys:
self.channel.queue_bind(
exchange='logs_rpc', queue='task_queue', routing_key=routing_key
) @lru_cache()
def fib(self, n):
"""
斐波那契数列.===>程序的处理逻辑
使用lru_cache 优化递归
:param n:
:return:
"""
if n == 0:
return 0
elif n == 1:
return 1
else:
return self.fib(n - 1) + self.fib(n - 2) def call_back(self, channel, method, properties, body):
print('------------------------------------------')
print('接收到的消息为(斐波那契数列的入参项为):{}'.format(str(body)))
print('消息的相关属性为:')
print(properties)
value = self.fib(int(body))
print('斐波那契数列的运行结果为:{}'.format(str(value))) # 交换机将消息发送到队列
self.channel.basic_publish(
exchange='',
routing_key=properties.reply_to,
body=str(value),
properties=pika.BasicProperties(
delivery_mode=2,
correlation_id=properties.correlation_id,
)) # 消费者对消息进行确认
self.channel.basic_ack(delivery_tag=method.delivery_tag) def receive_msg(self):
print('开始接受消息...')
self.channel.basic_qos(prefetch_count=1)
self.channel.basic_consume(
consumer_callback=self.call_back,
queue='task_queue',
no_ack=False, # 消费者对消息进行确认
consumer_tag=str(uuid.uuid4())
) def consume(self):
self.receive_msg()
self.channel.start_consuming() if __name__ == '__main__':
rabbit_consumer = RabbitServer()
rabbit_consumer.consume()

生产者实现:

"""
基于RabbitMQ实现RPC通信机制 --> 客户端
""" import pika
import uuid
import time class RabbitClient(object):
def __init__(self):
# 与RabbitMq服务器建立连接
self.conn = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost', port=5672)
)
self.channel = self.conn.channel() # 声明一个exchange交换机,交换机的类型为topic
self.channel.exchange_declare(
exchange='logs_rpc', exchange_type='topic', durable=True
) # 声明一个回调队列,用于接受RPC回调结果的运行结果
result = self.channel.queue_declare(durable=True, exclusive=False)
self.call_queue = result.method.queue # 从回调队列当中获取运行结果.
self.channel.basic_consume(
consumer_callback=self.on_response,
queue=self.call_queue,
no_ack=False
) def on_response(self, channel, method, properties, body):
"""
对收到的消息进行确认
找到correlation_id与服务端的消息标识匹配的消息结果
:param channel:
:param method:
:param properties:
:param body:
:return:
"""
if self.corr_id == properties.correlation_id:
self.response = body
print('斐波那契数列的RPC返回结果是:{}'.format(body))
print('相关属性信息:')
print(properties)
self.channel.basic_ack(delivery_tag=method.delivery_tag) def send_msg(self, routing_key, message):
"""
exchange交换机将根据消息的路由键将消息路由到对应的queue当中
:param routing_key: 消息的路由键
:param message: 生成者发送的消息
:return:
"""
self.response = None
self.corr_id = str(uuid.uuid4())
self.channel.basic_publish(
exchange='logs_rpc',
routing_key=routing_key,
body=message,
properties=pika.BasicProperties(
delivery_mode=2,
correlation_id=self.corr_id,
reply_to=self.call_queue,
)) while self.response is None:
print('等待远程服务端的返回结果...')
self.conn.process_data_events() # 非阻塞式的不断获取消息. return self.response def close(self):
self.conn.close() if __name__ == "__main__":
rabbit_producer = RabbitClient()
routing_key = 'hello every one'
start_time = int(time.time())
for item in range(2000):
num = str(item)
print('生产者发送的消息为:{}'.format(num))
rabbit_producer.send_msg(routing_key, num)
end_time = int(time.time())
print("耗时{}s".format(str(end_time - start_time)))

计算2000以内的斐波拉契数列,执行结果如下:

RabbitMQ中RPC的实现及其通信机制的更多相关文章

  1. 基于RabbitMQ的Rpc框架

    参考文档:https://www.cnblogs.com/ericli-ericli/p/5917018.html 参考文档:RabbitMQ 实现RPC MQ的使用场景大概包括解耦,提高峰值处理能力 ...

  2. RabbitMQ 实现RPC

    实现RPC 首先要弄明白,RPC是个什么东西. (RPC) Remote Procedure Call Protocol 远程过程调用协议 在一个大型的公司,系统由大大小小的服务构成,不同的团队维护不 ...

  3. RabbitMQ中的RPC实现

    1.RPC简述 RPC,Remote Procedure Call 远程过程调用.通俗讲,两段程序不在同一个内存空间,无法直接通过方法名调用,就需要通过网络通信方式调用.对于RabbitMQ,本身就是 ...

  4. TensorFlow中的通信机制——Rendezvous(二)gRPC传输

    背景 [作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] 本篇是TensorFlow通信机制系列的第二篇文章,主要梳理使用gRPC网络传 ...

  5. Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制

    Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制 JAVA 中原生的 socket 通信机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.co ...

  6. Android中的常见通信机制和Linux中的通信机制

    Handler Handler是Android系统中的一种消息传递机制,起作用是应对多线程场景.将A进程的消息传递给B线程,实现异步消息处理.很多情况是将工作线程中需要更新UI的操作消息传递给UI主线 ...

  7. .Net中Remoting通信机制简单实例

    .Net中Remoting通信机制 前言: 本程序例子实现一个简单的Remoting通信案例 本程序采用语言:c# 编译工具:vs2013工程文件 编译环境:.net 4.0 程序模块: Test测试 ...

  8. .Net中Remoting通信机制

    Remoting通信机制 Remoting介绍 主要元素 通道类型 激活方式 对象定义 Remoting介绍 什么是Remoting,简而言之,我们可以将其看作是一种分布式处理方式. 从微软的产品角度 ...

  9. MEF插件系统中通信机制的设计和实现

    MEF插件系统中通信机制的设计和实现 1.背景 一般的WinForm中通过C#自带的Event机制便能很好的实现事件的注册和分发,但是,在插件系统中却不能这么简单的直接用已有的类来完成.一个插件本不包 ...

随机推荐

  1. SSL证书安装(Tomcat)腾讯云服务器

    一.SSL证书免费领取地址一年的 https://www.toolmao.com/get-free-ssl 什么你们公司买的?每次免费领取一年,能不能轮流领取没试过.商鸡,商鸡.... 二.下载SSL ...

  2. HDU 2717(* bfs)

    题意是在一个数轴上,每次可以一步到达当前位置数值的 2 倍的位置或者数值 +1 或数值 -1 的位置,给定 n 和 k,问从数值为 n 的位置最少多少步可以到达数值为 k 的位置. 用广搜的方法,把已 ...

  3. ArcGis使用字段别名Alias Name导出Excel

    在ArcMap10.3+(根据官网描述应该是,作者测试使用10.5,可行)以后的版本,可以使用ArcToolbox工具导出Excel. 工具位置ConversionTools——Excel——Tabl ...

  4. 开源顶级持久层框架——mybatis(ibatis)——day01

    mybatis-day01     1.对原生态jdbc程序中的问题总结         1.1环境             java环境:jdk             eclipse:indigo ...

  5. arcgis图层 GraphicsLayer与FeatureLayer

    什么是图层 图层是用来在 ArcGIS 产品套件中显示地理数据集的机制.每个图层代表一种数据集(可以是地图服务.图形或是矢量数据),并指定该数据集是如何描绘使用一组属性的. 包含一个地图控件的每个应用 ...

  6. Ubuntu18.04应用程序安装集锦

    整理网上的资源: Python Web开发工具箱 ubuntu美化及超NB的zsh配置 api文档查询工具:zeal,dash(收费)

  7. Timer定时方法(间隔时间后执行)

    Timer time = new Timer(); time.schedule(new TimerTask() { @Override public void run() { // TODO Auto ...

  8. python序列化与反序列化(json与pickle)

    在python中,序列化可以理解为将python中对象的编码格式转换为json(pickle)格式的字符串,而反序列化可以 理解为将json(pickle)格式的字符串转换为python中对象的编码格 ...

  9. LeetCode第二十题-有效的括号

    Valid Parentheses 问题简介: 给定一个只包含字符 ‘(’ , ‘)’ , ‘{’ , ‘}’ , ‘[’ , ‘]’ 的字符串,确定输入字符串是否有效 有效的条件: 必须使用相同类型 ...

  10. Spring Cloud 2-RabbitMQ 集成(八)

    Spring Cloud  RabbitMQ  pom.xml application.yml 提供者 消费者 队列配置 单元测试 通过消息队列MQ做为通信中心,这里采用RabbitMQ.安装方参考: ...