简体   繁体   English

Pyhon Pika如何使用GeventConnection

[英]Pyhon Pika how to use GeventConnection

We have several tasks that we consume from a message queue.我们有几个从消息队列中使用的任务。 The runtimes of those tasks are dependent on fetching some data from a database.这些任务的运行时间取决于从数据库中获取一些数据。 Therefore we would like to work with Gevent to not block the program if some database requests take a long time.因此,如果某些数据库请求需要很长时间,我们希望与Gevent合作,不要阻止程序。 We are trying to couple it with the Pika client, which has some asynchronous adapters, one of them for gevent: pika.adapters.gevent_connection.GeventConnection .我们正试图将它与Pika客户端结合起来,它有一些异步适配器,其中之一是用于 gevent 的: pika.adapters.gevent_connection.GeventConnection

I set up some toy code, which consumes from a MQ tasks that consists of integers and publishes them on another queue, while sleeping for 4 seconds for each odd number:我设置了一些玩具代码,它从一个由整数组成的 MQ 任务中消耗并将它们发布到另一个队列,同时为每个奇数休眠 4 秒:

# from gevent import monkey
# # Monkeypatch core python libraries to support asynchronous operations.
# monkey.patch_time()

import pika
from pika.adapters.gevent_connection import GeventConnection
from datetime import datetime
import time


def handle_delivery(unused_channel, method, header, body):
    """Called when we receive a message from RabbitMQ"""
    print(f"Received: {body} at {datetime.now()}")
    channel.basic_ack(method.delivery_tag)

    num = int(body)
    print(num)

    if num % 2 != 0:
        time.sleep(4)

    channel.basic_publish(
        exchange='my_test_exchange2',
        routing_key='my_test_queue2',
        body=body
    )

    print("Finished processing")


def on_connected(connection):
    """Called when we are fully connected to RabbitMQ"""
    # Open a channel
    connection.channel(on_open_callback=on_channel_open)


def on_channel_open(new_channel):
    """Called when our channel has opened"""
    global channel
    channel = new_channel
    channel.basic_qos(prefetch_count=1)
    channel.queue_declare(queue="my_queue_gevent5")
    channel.exchange_declare("my_test_exchange2")
    channel.queue_declare(queue="my_test_queue2")
    channel.queue_bind(exchange="my_test_exchange2", queue="my_test_queue2")
    channel.basic_consume("my_queue_gevent5", handle_delivery)


def start_loop(i):
    conn = GeventConnection(pika.ConnectionParameters('localhost'), on_open_callback=on_connected)
    conn.ioloop.start()


start_loop(1)

If I run it without the monkey.patch_time() call it works OK and it publishes results on the my_test_queue2 , but it works sequentially.如果我在没有调用monkey.patch_time()的情况下运行它,它可以正常工作,并且它会在my_test_queue2上发布结果,但它会按顺序工作。 The expected behaviour after adding monkey.patch_time() patch would be that it still works but concurrently.添加monkey.patch_time()补丁后的预期行为是它仍然有效但同时发生。 However, the code gets stuck (nothing happens anymore) after it comes to the call time.sleep(4) .但是,代码在调用time.sleep(4) It processes and publishes the first integer, which is 0, and then gets stuck at 1, when the if clause gets triggered.它处理并发布第一个 integer,即 0,然后当 if 子句被触发时卡在 1。 What am I doing wrong?我究竟做错了什么?

With the help of ChatGPT I managed to make it work.ChatGPT的帮助下,我设法让它工作了。 There was a gevent.spawn() call missing:缺少一个gevent.spawn()调用:

def handle_delivery(unused_channel, method, header, body):
    print("Handling delivery")
    gevent.spawn(process_message, method, body)


def process_message(method, body):
    print(f"Received: {body} at {datetime.now()}")
    channel.basic_ack(method.delivery_tag)

    num = int(body)
    print(num)

    if num % 2 != 0:
        time.sleep(4)

    channel.basic_publish(
        exchange='my_test_exchange2',
        routing_key='my_test_queue2',
        body=body
    )

    print("Finished processing")

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

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