day11-rabbit MQ rpc remote procedure call
一、前言
转载师兄博客
之前我们都是单向发送消息,客户端发送消息给服务端,那么问题来了,我现在发一个命令给远程客户端,让它去执行,执行之后的结果,我想把这个结果再返回。这个模型叫什么呐,这种模型叫RPC=>remote procedure call。
怎么返回这个消息呢?
答:就server 端和客户端既是消费者,又是生产者。
想要深入了解RabbitMQ:猛击这里
二、模型图

三、逻辑代码
3.1、RPC Client
1 import pika,uuid,time 2 3 class FibonacciRpcClient(object): 4 "斐波那契数列rpc客户端" 5 6 def __init__(self): 7 self.connection = pika.BlockingConnection(pika.ConnectionParameters 8 (host="localhost")) 9 self.channel = self.connection.channel() 10 result = self.channel.queue_declare(exclusive=True) 11 self.callback_queue = result.method.queue 12 self.channel.basic_consume(self.on_response,no_ack=True, 13 queue=self.callback_queue) 14 15 def on_response(self,ch,method,props,body): 16 print("---->",method,props) 17 if self.corr_id == props.correlation_id: #我发过去的结果就是我想要的结果,保持数据的一致性 18 self.response = body 19 20 21 def call(self,n): 22 self.response = None 23 self.corr_id = str(uuid.uuid4()) 24 self.channel.publish(exchange="", 25 routing_key="rpc_queue", 26 properties=pika.BasicProperties( 27 reply_to=self.callback_queue, 28 correlation_id=self.corr_id), 29 body=str(n)) 30 while self.response is None: 31 self.connection.process_data_events() #非阻塞版的start_consumer() 32 print("no msg....") 33 time.sleep(0.5) 34 return int(self.response) 35 36 if __name__ == "__main__": 37 fibonacci_rpc = FibonacciRpcClient() 38 print(" [x] Requesting fib(30)") 39 response = fibonacci_rpc.call(10) 40 print(" [.] Got %r" % response)
注:
- 我是想不阻塞,而是想每过一段时间,就过来检查一下,就不能用start_consumer,而是用connection.process_data_evevts(),它是不阻塞的,如果收到消息就收到,收不到消息也返回,就继续往下执行。
- reply_to就是想让服务器执行完命令之后,把结果返回到这个queue里面。
- 在while self.respose is None中的代码我可以不做time.sleep,我这边可以发消息给服务器端,这个消息不一定按顺序发给服务器端,如果不做self.corr_id == props.correlation_id的验证,那数据就可能对不上了。
3.2、RPC Server
1 import pika 2 3 connection = pika.BlockingConnection(pika.ConnectionParameters(host="localhost")) 4 channel = connection.channel() 5 channel.queue_declare(queue="rpc_queue") 6 7 def fib(n): 8 "斐波那契数列" 9 if n == 0: 10 return 0 11 elif n == 1: 12 return 1 13 else: 14 return fib(n-1)+fib(n-2) 15 16 17 def on_request(ch,method,props,body): 18 n = int(body) 19 print(" [.] fib(%s)" % n) 20 response = fib(n) 21 ch.basic_publish(exchange="", 22 routing_key=props.reply_to, 23 properties=pika.BasicProperties(correlation_id=\ 24 props.correlation_id),#props的是客户端的发过来的信息,这边把correlation_id返回给客户端做验证 25 body=str(response)) 26 ch.basic_ack(delivery_tag=method.delivery_tag) 27 28 channel.basic_qos(prefetch_count=1) 29 channel.basic_consume(on_request,queue="rpc_queue") 30 31 print(" [x] Awaiting RPC requests") 32 channel.start_consuming()
注:props.reply_to,这个就是客户端返回过来的queue。
问:如果客户端和服务用的是同一个queue,会有什么影响?
答:如果客户端也发到rpc_queue中,那么客户端就会收到自己的消息,就会形成一个死循坏,把自己给玩死了。

浙公网安备 33010602011771号