[英]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.