一、前言

  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. Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift

    1. 摘要 训练深层的神经网络非常困难,因为在训练的过程中,随着前面层数参数的改变,每层输入的分布也会随之改变.这需要我们设置较小的学习率并且谨慎地对参数进行初始化,因此训练过程比较缓慢. 作者将这种 ...

  2. Halcon学习网

    重码网是一个在线机器视觉学习网站,推出了Halcon,Visionpro机器视觉学习视频教程,视频内容通俗易懂,没有编程基础的同学,照着视频练习,也同样可以学会. 学机器视觉,拿高薪,成就技术大拿.重 ...

  3. JVM监控及堆栈内存

    jconsole 堆内存:存放new出来的对象 栈内存:存放基本数据结构和对象的引用,但对象本身放在堆中

  4. Amazon Headlines Update on Activity in US West Coast Ports

    According to news reports, freighter cargo may not be offloaded at U.S. West Coast ports from Februa ...

  5. UI优秀框架(库)

    1.vux 官网:https://doc.vux.li/zh-CN/ Github:https://github.com/airyland/vux 13818  Stars  3064 Forks   ...

  6. OrderSys---Spring 计划(第一天)

    Sprint 计划会议: 目标: 1.了解需求分析书的内容 2.划分OrderSys的功能模块 3.开始制作原型 Sprint 3 Backlog细化: ID Name Est How to demo ...

  7. Beta冲刺第二周王者荣耀交流协会第三次会议

    1.例会照片: 成员王超,高远博,冉华,王磊,王玉玲,任思佳,袁玥全部到齐 master:袁玥 2.时间跨度: 2017年11月19日 17:00 — 17:11,总计11分钟. 3.地 点: 一食堂 ...

  8. 20162320MyOD重做版

    博客说明 由于上次的MyOD.java没有得分,所以这次我重做了这个java,代码是自己完成的,请教了一些同学的思路.故补交一篇博客来说明我对每一步代码的编写的想法以及理解. 代码片段及理解 1.先创 ...

  9. 按照Right-BICEP要求设计四则运算3程序的单元测试用例

    按照Right-BICEP要求: Right——结果是否正确? B——是否所有的边界条件都是正确的? I——能查一下反响关联吗? C——能用其它手段交叉检查一下吗? E——你是否可以强制错误条件发生? ...

  10. 开发环境解决 kafka Failed to send messages after 3 tries

    新建了一个kafka集群,在window下写了一个简单的producer做测试,结果遇到了消息发送失败的问题,代码如下: Properties props = new Properties(); pr ...