简体   繁体   English

使用Pika的Rabbitmq远程通话

[英]Rabbitmq remote call with Pika

I am new to rabbitmq and trying to figure out how I can make a client request a server with information about memory and CPU utilization with this tutorial ( https://www.rabbitmq.com/tutorials/tutorial-six-python.html ). 我是Rabbitmq的新手,并试图通过本教程( https://www.rabbitmq.com/tutorials/tutorial-six-python.html )使客户端如何请求服务器提供有关内存和CPU利用率的信息。 。

So the client requests for CPU and memory ( I believe I will need two queues) and the server respond with the values. 因此,客户端请求CPU和内存(我相信我将需要两个队列),服务器将使用这些值进行响应。

Is there anyway to simple create a client.py and server.py with this case using the Pika library in Python. 无论如何,在这种情况下,可以使用Python中的Pika库简单地创建一个client.pyserver.py

I would recommend you to follow the first RabbitMQ tutorials if you haven't already. 如果您还没有的话,我建议您先阅读RabbitMQ教程 The RPC example builds on concepts covered on previous examples (direct queues, exclusive queues, acknowledgements, etc.). RPC示例基于先前示例(直接队列,排他队列,确认等)中涵盖的概念。

The RPC solution proposed on the tutorial requires at least two queues, depending on how many clients you want to use: 本教程中提出的RPC解决方案至少需要两个队列,具体取决于您要使用多少个客户端:

  • One direct queue ( rpc_queue ), used to send requests from the client to the server. 一个直接队列( rpc_queue ),用于将请求从客户端发送到服务器。
  • One exclusive queue per client, used to receive responses. 每个客户端一个独占队列,用于接收响应。

The request/response cycle: 请求/响应周期:

  • The client sends a message to the rpc_queue . 客户端将消息发送到rpc_queue Each message includes a reply_to property, with the name of the client exclusive queue the server should reply to, and a correlation_id property, which is just an unique id used to track the request. 每个消息包括一个reply_to属性,与所述客户端独占队列服务器应该答复的名称,和一个correlation_id属性,它是用来跟踪请求只是一个唯一的ID。
  • The server waits for messages on the rpc_queue . 服务器在rpc_queue上等待消息。 When a message arrives, it prepares the response, adds the correlation_id to the new message, and sends it to the queue defined in the reply_to message property. 消息到达时,它将准备响应,将correlation_id添加到新消息,然后将其发送到在reply_to message属性中定义的队列。
  • The client waits on its exclusive queue until it finds a message with the correlation_id that was originally generated. 客户端等待其排他队列,直到找到最初生成的具有correlation_id的消息。

Jumping straight to your problem, the first thing to do is to define the message format you'll want to use on your responses. 直接跳到您的问题,首先要做的是定义要在响应中使用的消息格式。 You can use JSON, msgpack or any other serialization library. 您可以使用JSON,msgpack或任何其他序列化库。 For example, if using JSON, one message could look something like this: 例如,如果使用JSON,一条消息可能看起来像这样:

{
    "cpu": 1.2,
    "memory": 0.3
} 

Then, on your server.py : 然后,在您的server.py

def on_request(channel, method, props, body):
    response = {'cpu': current_cpu_usage(),
                'memory': current_memory_usage()}
    properties = pika.BasicProperties(correlation_id=props.correlation_id)

    channel.basic_publish(exchange='',
                          routing_key=props.reply_to,
                          properties=properties,
                          body=json.dumps(response))
    channel.basic_ack(delivery_tag=method.delivery_tag)

# ...

And on your client.py : 并在您的client.py

class ResponseTimeout(Exception): pass

class Client:
    # similar constructor as `FibonacciRpcClient` from tutorial...

    def on_response(self, channel, method, props, body):
        if self.correlation_id == props.correlation_id:
            self.response = json.loads(body.decode())

    def call(self, timeout=2):
        self.response = None
        self.correlation_id = str(uuid.uuid4())
        self.channel.basic_publish(exchange='',
                                   routing_key='rpc_queue',
                                   properties=pika.BasicProperties(
                                       reply_to=self.callback_queue,
                                       correlation_id=self.correlation_id),
                                   body='')

        start_time = time.time()
        while self.response is None:
            if (start_time + timeout) < time.time():
                raise ResponseTimeout()
            self.connection.process_data_events()
        return self.response

As you see, the code is pretty much the same as the original FibonacciRpcClient . 如您所见,代码与原始FibonacciRpcClient几乎相同。 The main differences are: 主要区别在于:

  • We use JSON as data format for our messages. 我们使用JSON作为消息的数据格式。
  • Our client call() method doesn't require a body argument (there's nothing to send to the server) 我们的客户端call()方法不需要body参数(没有任何内容可发送到服务器)
  • We take care of response timeouts (if the server is down, or if it doesn't reply to our messages) 我们负责响应超时(如果服务器已关闭,或者它没有回复我们的消息)

Still, there're a lot of things to improve here: 不过,这里还有很多地方需要改进:

  • No error handling: For example, if the client "forgets" to send a reply_to queue, our server is gonna crash, and will crash again on restart (the broken message will be requeued infinitely as long as it isn't acknowledged by our server) 没有错误处理:例如,如果客户端“忘记了”发送一个reply_to队列,我们​​的服务器将崩溃,并且将在重新启动时再次崩溃(只要我们的服务器未确认该破损的消息就会无限地重新排队) )
  • We don't handle broken connections (no reconnection mechanism) 我们不处理断开的连接(没有重新连接机制)
  • ... ...

You may also consider replacing the RPC approach with a publish/subscribe pattern; 您也可以考虑使用发布/订阅模式替换RPC方法。 in this way, the server simply broadcasts its CPU/memory state every X time interval, and one or more clients receive the updates. 这样,服务器只需在每个X时间间隔内广播其CPU /内存状态,一个或多个客户端就可以接收更新。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM