前提:一个进程一个 amqp 连接

我本来想用多线程来实现,但是貌似做不到:一个连接,多个线程消费

但是我又不想一个线程一个连接,这样太浪费连接数了

然后我想到 nameko 是一个进程一个连接,然后使用 evnetlet 协程来实现,并发消费

所以我写了下面的 demo

from loguru import logger
from kombu.transport.pyamqp import Message
from kombu import Exchange, Queue
from kombu import Connection, Consumer, Queue
from concurrent.futures import ThreadPoolExecutor
import time
import eventlet
eventlet.monkey_patch()


amqp_uri = 'amqp://pon:pon@192.168.31.245:5672//'

pool = eventlet.GreenPool(10)


def handle_message(message: Message):
    logger.debug(message)
    logger.debug(message.body)
    time.sleep(1)
    message.ack(multiple=True)


refresh_exchange = Exchange('refresh', type='topic')

imdb_queue = Queue('refresh_imdb', refresh_exchange,
                   routing_key='to_imdb', durable=True)


queues: list[Queue] = [imdb_queue]


def start_consuming(message: Message):
    pool.spawn_n(handle_message, message)


with Connection(amqp_uri) as conn:
    with conn.channel() as channel:
        consumer = Consumer(
            channel, queues=queues,
            prefetch_count=10, on_message=start_consuming
        )
        with consumer:
            while True:
                conn.drain_events()

  • 消费一个任务需要 1 秒
  • 预取 10 个
  • 协程池 size 为 10

从下面的消费数据可以看出,是一秒消费 10 个

所以是实现了并发的

图片.png


universe_king
3.4k 声望680 粉丝