rabbitmq之rpc工作模式

1. 概括

rpc工作模式: 通过消息队列实现rpc功能, 客户端发送消息到消费队列, 服务端进行消费消息执行程序将结果再发送到回调队列, 供客户端使用. 是一种双向生产消费模式.

既是生产者又是消费者, 如果只有一个queue 则会出现死循环, 此时需要有一个回调队列.

客户端发消息时, 消息属性要设置上reply_to的回调队列, 把消息发送到指定的rpc队列, 通过process_data_events来保持连接并且检查是否有回调, 

服务端从rpc队列里来确认客户端是否有发消息, 如果有则进行消费处理执行要做的事, 将处理的结果发送到客户端传来的回调队列里供客户端使用.

2.示例

客户端传入数据, 服务端进行冒泡排序 再将结果返回给客户端.

结果展示

rabbitmq之rpc工作模式_第1张图片

rabbitmq之rpc工作模式_第2张图片

客户端demo

import pika
import uuid
import json
import random


class BubbleSortRpcClient(object):
    def __init__(self):
        self.username = 'sanford'
        self.password = '123456'
        self.host = 'localhost'
        self.port = 5672
        self.virtual_host = 'sanford_host'

        credentials = pika.PlainCredentials(username=self.username, password=self.password)
        params = pika.ConnectionParameters(host=self.host,
                                           port=self.port,
                                           virtual_host=self.virtual_host,
                                           credentials=credentials)

        # 创建连接
        self.connection = pika.BlockingConnection(params)

        # 创建信道
        self.channel = self.connection.channel()

        # 声明一个队列用于接收服务端返回结果, exclusive=True 只允许当前连接访问
        result = self.channel.queue_declare(queue='', exclusive=True, durable=True)
        self.callback_queue = result.method.queue

        # 接收服务端返回的结果进行消费
        self.channel.basic_consume(queue=self.callback_queue,
                                   on_message_callback=self.on_response)

    def on_response(self, ch, method, props, body):
        """
        接收到服务端返回的结果的回调函数
        """
        if self.corr_id == props.correlation_id:
            if isinstance(body, str):
                self.response = body
            else:
                self.response = json.loads(body)

        ch.basic_ack(delivery_tag=method.delivery_tag)

    def call(self, ls):
        self.response = None
        self.corr_id = str(uuid.uuid4())

        # 请求消息属性设置 reply_to:接收服务端消息的队列
        properties = pika.BasicProperties(delivery_mode=2,
                                          reply_to=self.callback_queue,
                                          correlation_id=self.corr_id)
        # 发送请求消息
        self.channel.basic_publish(exchange='',
                                   routing_key='rpc_queue',
                                   body=json.dumps(ls),
                                   properties=properties)

        while self.response is None:
            # 保持连接 检查是否有回调
            self.connection.process_data_events()
        return self.response


if __name__ == '__main__':
    bubble_sort = BubbleSortRpcClient()

    ls_list = [
        [1, 22, 3, 7, 4, 77, 34, 66, 5, 4, 8, 15],
        '2223, 35, 44',
        {2: 2, 3: 3},
        [4, 7, 3, 9],
        [3, 3, 9, 2]
    ]
    idx = random.randint(0, 4)
    print("客户端开始发起请求......")
    response = bubble_sort.call(ls_list[idx])
    print("服务端计算结果 response: {0}".format(response))

服务端demo 

import pika
import json


class BubbleSortRpcService(object):
    def __init__(self):
        self.username = 'sanford'
        self.password = '123456'
        self.host = 'localhost'
        self.port = 5672
        self.virtual_host = 'sanford_host'

    @staticmethod
    def bubble_sort(ls):
        """
        冒泡排序
        """
        for i in range(len(ls) - 1):
            for j in range(len(ls) - i - 1):
                if ls[j] > ls[j + 1]:
                    ls[j], ls[j + 1] = ls[j + 1], ls[j]
        return ls

    def on_request(self, ch, method, props, body):
        ls = json.loads(body)

        print("客户端请求参数 ls:{0}".format(ls))

        if isinstance(ls, list):
            response = self.bubble_sort(ls)
        else:
            response = '客户端请求参数类型不对 type:{0}'.format(type(ls))
        print("服务端计算结果 response:{0}".format(response))

        # 服务端发送消息的属性设置
        properties = pika.BasicProperties(delivery_mode=2,
                                          correlation_id=props.correlation_id)

        # 服务端发送计算后的结果, routing_key为客户端传来的reply_to
        ch.basic_publish(exchange='',
                         routing_key=props.reply_to,
                         properties=properties,
                         body=json.dumps(response))

        ch.basic_ack(delivery_tag=method.delivery_tag)

    def run(self):
        credentials = pika.PlainCredentials(username=self.username, password=self.password)
        params = pika.ConnectionParameters(host=self.host,
                                           port=self.port,
                                           virtual_host=self.virtual_host,
                                           credentials=credentials)
        connection = pika.BlockingConnection(params)
        channel = connection.channel()

        channel.queue_declare(queue='rpc_queue', durable=True)

        channel.basic_qos(prefetch_count=1)

        channel.basic_consume(queue='rpc_queue', on_message_callback=self.on_request)

        print("正在等待客户端请求......")
        channel.start_consuming()


if __name__ == '__main__':
    service = BubbleSortRpcService()
    service.run()

你可能感兴趣的:(开发工具,python,rabbitmq,rpc,分布式)