You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中RabbitMQ消息并行处理方案咨询(附多进程尝试代码)

问题分析与解决方案

你的代码串行执行的核心原因有两个:一是创建Process时错误地直接调用了函数(target=between_func()),导致主进程会先执行完between_func才会创建子进程;二是原架构没有将计算密集的generate_image任务真正分配到独立进程中执行。以下是针对性的优化方案:

方案1:使用进程池复用进程(推荐)

该方案通过进程池复用进程,避免每个任务重复加载StableDiffusion模型,大幅降低资源开销,同时保证计算任务的并行执行。

修改后的完整代码

import asyncio
import json
from multiprocessing import Pool
import aio_pika
from PIL import Image
from keras_cv.models import StableDiffusion

# 进程内全局模型变量,每个进程仅初始化一次
worker_model = None

def init_worker():
    """进程池初始化函数:每个进程启动时加载一次模型"""
    global worker_model
    worker_model = StableDiffusion(img_height=512, img_width=512, jit_compile=True)

def generate_image(task_args):
    """计算密集型任务:复用已加载的模型生成图片"""
    prompt, task_id = task_args
    img = worker_model.text_to_image(
        prompt=prompt,
        batch_size=1,
        num_steps=10,
        seed=1539,
    )
    image_name = f'images/{task_id}.png'
    Image.fromarray(img[0]).save(image_name)

async def main(pool):
    """RabbitMQ异步消费者:接收消息并提交到进程池"""
    connection = await aio_pika.connect_robust("amqp://guest:guest@127.0.0.1/")
    queue_name = "requestQueue"

    async with connection:
        channel = await connection.channel()
        await channel.set_qos(prefetch_count=10)  # 限制预取消息数量
        queue = await channel.declare_queue(queue_name, auto_delete=False, durable=True)
        
        async with queue.iterator() as queue_iter:
            async for message in queue_iter:
                async with message.process():
                    json_str = json.loads(message.body)
                    # 将任务提交到进程池,异步执行
                    pool.apply_async(generate_image, args=((json_str.get('message'), json_str.get('id')),))

if __name__ == "__main__":
    # 创建进程池,指定初始化函数加载模型
    with Pool(initializer=init_worker) as pool:
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        loop.run_until_complete(main(pool))
        loop.close()

方案优势

  • 进程复用:每个进程仅加载一次模型,避免重复加载的时间和资源消耗
  • 异步解耦:RabbitMQ消费者仅负责接收消息,不阻塞计算任务
  • 真正并行:计算任务在独立进程中执行,完全避开GIL限制

方案2:每个消息创建独立进程(适合低频率任务)

如果任务量较小,也可以为每个消息单独创建进程,缺点是每个进程都要重新加载模型,资源开销较高。

修改后的代码

import asyncio
import json
from multiprocessing import Process
import aio_pika
from PIL import Image
from keras_cv.models import StableDiffusion

def generate_image(prompt, task_id):
    """计算密集型任务:每次创建进程时加载模型"""
    model = StableDiffusion(img_height=512, img_width=512, jit_compile=True)
    img = model.text_to_image(
        prompt=prompt,
        batch_size=1,
        num_steps=10,
        seed=1539,
    )
    image_name = f'images/{task_id}.png'
    Image.fromarray(img[0]).save(image_name)

async def main():
    """RabbitMQ异步消费者:每个消息启动一个独立进程"""
    connection = await aio_pika.connect_robust("amqp://guest:guest@127.0.0.1/")
    queue_name = "requestQueue"

    async with connection:
        channel = await connection.channel()
        await channel.set_qos(prefetch_count=10)
        queue = await channel.declare_queue(queue_name, auto_delete=False, durable=True)
        
        async with queue.iterator() as queue_iter:
            async for message in queue_iter:
                async with message.process():
                    json_str = json.loads(message.body)
                    prompt = json_str.get('message')
                    task_id = json_str.get('id')
                    # 为每个消息创建独立进程并启动
                    p = Process(target=generate_image, args=(prompt, task_id))
                    p.start()

if __name__ == "__main__":
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(main())
    loop.close()

原代码的核心错误修正

你最初创建进程的代码存在语法错误:

# 错误写法:直接调用函数,主进程会先执行完between_func才创建子进程
t1 = Process(target=between_func())
# 正确写法:传递函数对象,子进程会独立执行该函数
t1 = Process(target=between_func)

即使修正该错误,这种"多消费者进程"的架构也只是让多个消费者并行接收消息,但每个消费者内部的generate_image仍会串行执行,不如上述两种方案高效。

内容的提问来源于stack exchange,提问作者Le Chat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 17:32:50