RabbitMQ实现的RPC
1.主要思路
1.生产者发布任务时,指定properties,告知消费者处理任务完毕之后,将结果存储到reply_to指定的Queue中,本次任务的id是correlation_id
2.消费者消费完消息,即处理完任务,将结果存储到reply_to指定的Queue中,同时指定correlation_id为从任务中获取的id
3.生产者先前已经订阅过reply_to指定的Queue,当消费者把结果回传到队列中时,生产者就可以取出结果,并对比correlation_id是否是自己想要的id以确认是否是自己发送的任务。
2.消费者代码
- #_*_coding:utf-8_*_
- import pika
- import time
- # 链接socket
- connection = pika.BlockingConnection(pika.ConnectionParameters(
- host='localhost'))
- channel = connection.channel()
- # 生成rpc queue
- channel.queue_declare(queue='rpc_queue')
- # 斐波那契数列
- def fib(n):
- if n == 0:
- return 0
- elif n == 1:
- return 1
- else:
- return fib(n-1) + fib(n-2)
- # 收到消息就调用
- # ch 管道内存对象地址
- # method 消息发给哪个queue
- # props 返回给消费的返回参数
- # body数据对象
- def on_request(ch, method, props, body):
- n = int(body)
- print(" [.] fib(%s)" % n)
- # 调用斐波那契函数 传入结果
- response = fib(n)
- ch.basic_publish(exchange='',
- # 生产端随机生成的queue
- routing_key=props.reply_to,
- # 获取UUID唯一 字符串数值
- properties=pika.BasicProperties(correlation_id = \
- props.correlation_id),
- # 消息返回给生产端
- body=str(response))
- # 确保任务完成
- ch.basic_ack(delivery_tag = method.delivery_tag)
- # rpc_queue收到消息:调用on_request回调函数
- # queue='rpc_queue'从rpc内收
- channel.basic_consume(on_request, queue='rpc_queue')
- print(" [x] Awaiting RPC requests")
- channel.start_consuming()
3.生产者代码
- import pika
- import uuid
- import time
- # 斐波那契数列 前两个数相加依次排列
- class FibonacciRpcClient(object):
- def __init__(self):
- # 链接远程
- self.connection = pika.BlockingConnection(pika.ConnectionParameters(
- host='localhost'))
- self.channel = self.connection.channel()
- # 生成随机queue
- #如果你想创建一个只有自己可见的队列,即不允许其它用户访问,RabbitMQ允许你将一个Queue声明成为排他性的(Exclusive Queue)。
- result = self.channel.queue_declare(exclusive=True)
- # 随机取queue名字,发给消费端
- self.callback_queue = result.method.queue
- # self.on_response 回调函数:只要收到消息就调用这个函数。
- # 声明收到消息后就 收queue=self.callback_queue内的消息
- self.channel.basic_consume(self.on_response, no_ack=True,
- queue=self.callback_queue)
- # 收到消息就调用
- # ch 管道内存对象地址
- # method 消息发给哪个queue
- # body数据对象
- def on_response(self, ch, method, props, body):
- # 判断本机生成的ID 与 生产端发过来的ID是否相等
- if self.corr_id == props.correlation_id:
- # 将body值 赋值给self.response
- self.response = body
- def call(self, n):
- # 赋值变量,一个循环值
- self.response = None
- # 随机一次唯一的字符串
- self.corr_id = str(uuid.uuid4())
- # routing_key='rpc_queue' 发一个消息到rpc_queue内
- self.channel.basic_publish(exchange='',
- routing_key='rpc_queue',
- properties=pika.BasicProperties(
- # 执行命令之后结果返回给self.callaback_queue这个队列中
- reply_to = self.callback_queue,
- # 生成UUID 发送给消费端
- correlation_id = self.corr_id,
- ),
- # 发的消息,必须传入字符串,不能传数字
- body=str(n))
- # 没有数据就循环收
- while self.response is None:
- # 非阻塞版的start_consuming()
- # 没有消息不阻塞
- self.connection.process_data_events()
- print("no msg...")
- time.sleep(0.5)
- return int(self.response)
- # 实例化
- fibonacci_rpc = FibonacciRpcClient()
- print(" [x] Requesting fib(30)")
- response = fibonacci_rpc.call(10)
- print(" [.] Got %r" % response)
RabbitMQ实现的RPC的更多相关文章
- RabbitMQ中的RPC实现
1.RPC简述 RPC,Remote Procedure Call 远程过程调用.通俗讲,两段程序不在同一个内存空间,无法直接通过方法名调用,就需要通过网络通信方式调用.对于RabbitMQ,本身就是 ...
- RabbitMQ学习之RPC(6)
在第二个教程中,我们了解到如何在多个worker中使用Work Queues分发费时的任务. 但是,如果我们需要在远程运行一个函数并且等待结果该怎么办呢?这个时候,我们需要另外一个模式了.这种模式通常 ...
- rabbitmq学习(四):利用rabbitmq实现远程rpc调用
一.rabbitmq实现rpc调用的原理 ·rabbitmq实现rpc的原理是:客户端向一个队列中发送消息,并注册一个回调的队列用于接收服务端返回的消息,该消息需要声明一个叫做correaltionI ...
- 基于RabbitMQ的跨平台RPC框架
RabbitMQRpc protocobuf RabbitMQ 实现RPC https://www.cnblogs.com/LiangSW/p/6216537.html 基于RabbitMQ的RPC ...
- python项目开发:用RabbitMQ实现异步RPC
程序要求: 1. 用Rabbit MQ实现RPC 1. 可以异步地执行多条命令 2. 可以对一次性对多个机器执行命令 程序效果: --->run dir host1 host2 .... --- ...
- 8.RabbitMQ系列之RPC
1. RPC Remote Procedure Call:远程过程调用,一次远程过程调用的流程即客户端发送一个请求到服务端,服务端根据请求信息进行处理后返回响应信息,客户端收到响应信息后结束 2. C ...
- 【译】RabbitMQ:远程过程调用(RPC)
在教程二中,我们学习了如何使用工作队列在多个工作线程中分发耗时的任务.但如果我们需要去执行远程机器上的方法并且等待结果会怎么样呢?那又是另外一回事了.这种模式通常被称为远程过程调用(RPC). 本教程 ...
- (转)RabbitMQ消息队列(七):适用于云计算集群的远程调用(RPC)
在云计算环境中,很多时候需要用它其他机器的计算资源,我们有可能会在接收到Message进行处理时,会把一部分计算任务分配到其他节点来完成.那么,RabbitMQ如何使用RPC呢?在本篇文章中,我们将会 ...
- RabbitMQ系列教程之六:远程过程调用(RPC)
远程过程调用(Remote Proceddure call[RPC])(本实例都是使用的Net的客户端,使用C#编写) 在第二个教程中,我们学习了如何使用工作队列在多个工作实例之间分配耗时的任务. ...
随机推荐
- 【D3D】Direct3D中LPRECT(上左右底)和LPoint(x,y)之前转换
D3DSprite.cpp void CD3DSprite::DrawText(CD3DFont *pFont, char *szString, RECT &DesRect, D3DCOLOR ...
- redhat安装xwindow环境
. yum groupinstall "X Window System" . yum groupinstall "GNOME Desktop Environment&qu ...
- lib文件反汇编
运行vc命令行,输入:dumpbin /disasm xxx.lib > test.txt lib就是obj文件打包起来的,可以用lib.exe解出来,下面是vc环境下的操作,其他环境,看命令行 ...
- 设计规范VS设计创造力,谁更胜一筹?
设计规范和设计创造力哪个更重要?这是一个颇具争议性的话题.如果是3年前问我这个问题我会毫不犹豫的选择设计创造力,毫无疑问,一个好的设计创造力真的是可以让人像打了鸡血一样疯狂. 原来在上大学的时候,我就 ...
- Microsoft DirectX SDK 2010 版本下载
Microsoft DirectX SDK 2010 版本下载 Version:Date Published:9.29.19626/7/2010File name:File size:DXSDK_Ju ...
- Find the squareroot
https://github.com/Premiumlab/Python-for-Algorithms--Data-Structures--and-Interviews/blob/master/Moc ...
- devart 放大招了
前面我纪念BDE 的文章里面说过,devart 会在今后在数据库存取技术上会有更大的 进步,没想到很快devart 放大招了.在最新的unidac 和sdac 中,devart 支持在非Windows ...
- 在用easyui中做CRUD功能时,当删除一行或多行数据后再点击修改会提示你选中了多行,如何解决这个bug了?
在用easyui中做CRUD功能时,当删除一行或多行数据后再点击修改会提示你选中了多行,如何解决这个bug了? 在删除成功后,加上这句话就可以了:$("#dg").datagrid ...
- 服务器的日志一直报Packet for query is too large (7632997 > 4194304). You can change this value on the server by setting the max_allowed_packet' variable.的解决方法
服务器的日志一直报Packet for query is too large (7632997 > 4194304). You can change this value on the serv ...
- 2018.08.21 NOIP模拟 xorand(01trie)
xorand 描述 有q次操作,每次操作是以下两种: 1. 加入一个数到集合中 2. 查询,查询当前数字与集合中的数字的最大异或值,最大and值,最大or值 输入 第一行1个正整数Q表示操作次数 接下 ...