一、前言

  MQ本身是基于异步的消息处理,前面的示例中所有的生产者(P)将消息发送到RabbitMQ后不会知道消费者(C)处理成功或者失败(甚至连有没有消费者来处理这条消息都不知道)。
但实际的应用场景中,我们很可能需要一些同步处理,需要同步等待服务端将我的消息处理完成后再进行下一步处理。这相当于RPC(Remote Procedure Call,远程过程调用)。在RabbitMQ中也支持RPC。

  

  

RabbitMQ中实现RPC的机制是:

  • 客户端发送请求(消息)时,在消息的属性(MessageProperties,在AMQP协议中定义了14中properties,这些属性会随着消息一起发送)中设置两个值replyTo(一个Queue名称,用于告诉服务器处理完成后将通知我的消息发送到这个Queue中)和correlationId(此次请求的标识号,服务器处理完成后需要将此属性返还,客户端将根据这个id了解哪条请求被成功执行了或执行失败)
  • 服务器端收到消息并处理
  • 服务器端处理完消息后,将生成一条应答消息到replyTo指定的Queue,同时带上correlationId属性
  • 客户端之前已订阅replyTo指定的Queue,从中收到服务器的应答消息后,根据其中的correlationId属性分析哪条请求被执行了,根据执行结果进行后续业务处理

二、事例代码

  求斐波那契数列

  client: 

import pika
import uuid class FibonacciRpcClient(object): def __init__(self):
# 初始化时创建连接
self.connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
# 初始化建立管道
self.channel = self.connection.channel()
# 这里是客户端接收服务端的返回
# 在此要声明一个queue,并且名称随机生成
result = self.channel.queue_declare(exclusive=True)
# 该callback_queue 指定了服务端返回时,用哪一个queue
self.callback_queue = result.method.queue
# 客户端处理服务端返回的消息,指定获取信息的队列queue 和 回调函数
self.channel.basic_consume(self.on_response,
no_ack=True,
queue=self.callback_queue) # 客户端的回调函数,用来处理服务端返回的数据
def on_response(self, ch, method, props, body):
# 客户端回调函数对服务端返回数据的处理
# 此correlation_id 为服务端返回的id, 用来确保处理的消息为同一条
if self.corr_id == props.correlation_id:
# 将返回的信息body 给 response
self.response = body # call函数就是client 最初发送消息的地方
def call(self, n):
self.response = None
# corr_id 其实有客户端最初生成,由最初rpc_queue发送给服务端
# 服务端接收后会在将这个id 返回,就是上面的correlation_id
# 如果 corr_id 和 correlation_id 一致,则可确保是同一个消息
self.corr_id = str(uuid.uuid4())
self.channel.basic_publish(exchange='',
routing_key='rpc_queue',
properties=pika.BasicProperties(
# reply_to指定了服务端返回时使用的queue
reply_to=self.callback_queue,
correlation_id=self.corr_id,
),
body=str(n)) # 客户端发送和接收消息的队列是不一样的
# 所以需要对接收消息的队列不断查询
# 如果有消息了就接收
while self.response is None:
# 当这里使用 channel.start_consumer() 为阻塞状态
# 使用connection.process_data_events() 为非阻塞
self.connection.process_data_events()
return int(self.response) if __name__ == '__main__': fibonacci_rpc = FibonacciRpcClient() while True:
num = int(input('>>:').strip())
response = fibonacci_rpc.call(num)
print(" [.] Got %r" % response)

  server: 

# -*- coding: UTF-8 -*-

import pika

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) # 回调函数
def on_request(ch, method, props, body):
n = int(body) print(" [.] fib(%s)" % n)
response = fib(n) ch.basic_publish(exchange='',
# 这个routing_key 定义了返回的队列是哪一个
# 就是客户端定义的 reply_to
routing_key=props.reply_to,
# correlation_id 就是客户端生成的corr_id
properties=pika.BasicProperties(
correlation_id=props.correlation_id),
body=str(response))
# 消息处理完毕后,主动告知rabbitmq
ch.basic_ack(delivery_tag=method.delivery_tag) # channel.basic_qos(prefetch_count=1)
channel.basic_consume(on_request,
queue='rpc_queue') print(" [x] Awaiting RPC requests")
channel.start_consuming()

 

Rabbitmq -- rpc的更多相关文章

  1. 【python】-- RabbitMQ RPC模型

    RabbitMQ RPC模型 RPC(remote procedure call)模型说通俗一点就是客户端发一个请求给远程服务端,让它去执行,然后服务端端再把执行的结果再返回给客户端. 1.服务端 i ...

  2. 8.rabbitmq RPC模拟微服务架构中的服务调用

    标题 : 8.rabbitmq RPC模拟微服务架构中的服务调用 目录 : RabbitMQ 序号 : 8 { var connectionFactory = new ConnectionFactor ...

  3. Openstack中RabbitMQ RPC代码分析

    在Openstack中,RPC调用是通过RabbitMQ进行的. 任何一个RPC调用,都有Client/Server两部分,分别在rpcapi.py和manager.py中实现. 这里以nova-sc ...

  4. python作业(第十一周)基于RabbitMQ rpc实现的主机管理

    作业需求: 可以对指定机器异步的执行多个命令 例子: >>:run "df -h" --hosts 192.168.3.55 10.4.3.4 task id: 453 ...

  5. 使用rabbitmq rpc 模式

        服务器端     安装 ubuntu 16.04 server     安装 rabbitmq-server     设置 apt 源 curl -s https://packagecloud ...

  6. Python自动化之rabbitmq rpc client端代码分析(原创)

    RPC调用client端解析 import pika import uuid # 建立连接 class FibonacciRpcClient(object): def __init__(self): ...

  7. RabbitMQ RPC问题

    1.服务器端代码:https://github.com/rabbitmq/rabbitmq-tutorials/blob/master/python/rpc_server.py 2.客户端代码:htt ...

  8. 基于RabbitMQ rpc实现的主机管理

    要求: 文件分布: 流程图: import pika import os import socket class Server(object): def __init__(self, queuenam ...

  9. Python RabbitMQ RPC实现

    远程调用方法:R(remote)  P(procedure)  C(call) 为了说明如何使用RPC服务,我们将创建一个简单的客户端类. 它将公开一个名为call的方法,它发送一个RPC请求和块,直 ...

随机推荐

  1. 基于preteus的1602液晶显示器的学习(LM016L)

    (证明学过,以示纪念) 所谓1602就是每行可以显示16个字符,可以显示两行.1602液晶在工业中使用比较广泛,其基本都采用的是HD44780控制器,或者兼容该指令集,因此基于HD44780写的控制程 ...

  2. 联邦快递 IE和IP的区别 Fedex IE VS Fedex IP

    什么是FedEx IP? FedEx IP指的是联邦快递优先服务,时效比较快些,相对来说价格也比普通的高一些. 什么是FedEx IE? FedEx IE指的是联邦快递经济服务,时效与FedEx IP ...

  3. redis利用key计时与计数

    计时 Setex 命令为指定的 key 设置值及其过期时间.如果 key 已经存在, SETEX 命令将会替换旧的值 基本命令: redis 127.0.0.1:6379> SETEX KEY_ ...

  4. springboot 集成 swagger

    1. 首先配置swaggerConfigpackage com.lixcx.lismservice.config; import com.lixcx.lismservice.format.Custom ...

  5. git实验

    四.实例应用 应用1.现有项目移植到git代管 进入目标项目,进行git初始化: 初始化:git init 修改config:git config -- local user.name '名称'  和 ...

  6. PHPDoc 学习记录

    https://zh.wikipedia.org/wiki/PHPDoc PHPDoc 是一个 PHP 版的 Javadoc.它是一种注释 PHP 代码的正式标准.它支持通过类似 phpDocumen ...

  7. "Hello World"团队召开的第三周第六次会议

    今天是我们团队“Hello World!”团队召开的第三周的第六次会议.博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七.燃尽图 一.会议时 ...

  8. CS小分队第一阶段冲刺站立会议(5月12日)

    昨日成果:2048整体界面效果经组员韩雪冬美化之后档次提升了好几个,我为其添加了保存并显示最高分数的功能. 遇到困难:当我想把access数据库由accdb改成mdb时,发生未知错误 ,导致数据库无法 ...

  9. javascript与python的比较

    1:javascript与python大小写皆敏感 2:javascript使用{}来组织代码块,与大部分语言相同  python使用缩进来组织代码块,与大部分语言不同,请务必遵守约定俗成的习惯,坚持 ...

  10. bootstrap 中的静态模式的控制按钮上的一个坑

    在使用modal时发现,代码:<button class="btn btn-danger" data-toggle="modal" data-target ...