Python分布式任务队列Celery如何实现负载均衡,让任务平均分配到每个worker节点?
目前小弟用 celery 搭了一套共 7 个 worker 节点的系统,主要是用于分散数据文件生成的任务,避免单个节点 I/O 过高,性能太差。目前小弟有几个问题:
1、一次性大量通过 apply_async 调用异步任务时,worker 对任务的获取是抢占式的,导致各个节点上的任务并不平均,有的节点早早就结束了所有的任务闲了下来,但是其他节点还在埋头苦干,请问 celery 有什么负载均衡的办法吗?如何让加入队列的任务平均分配在每个 worker 节点上呢?
2、worker 对于任务是先抢光队列里面的所有任务,然后再执行任务。请问是否有办法让每个节点只获取 worker_concurrency 数量的任务,哪个 process 完成了再去队列中获取呢?
谢谢大家~
Python分布式任务队列Celery如何实现负载均衡,让任务平均分配到每个worker节点?
这个问题不应该解决队列吧。
能详细讲讲具体做什么吗?这个抢占指的又是什么?是网络还是?有 ack 吗?
Celery的负载均衡主要靠broker的消息队列机制和worker的预取(prefetch)设置来实现。默认的轮询(round-robin)策略就能让任务平均分配,但需要合理配置。
关键配置点:
- broker_transport_options - 设置队列的负载均衡策略:
app.conf.broker_transport_options = {
'queue_order_strategy': 'round_robin', # 默认就是轮询
}
- worker_prefetch_multiplier - 控制每个worker预取任务数:
app.conf.worker_prefetch_multiplier = 1 # 每个worker一次只预取1个任务
设为1能确保严格平均分配,但可能影响吞吐量。默认值是4,worker会多预取几个任务。
- 启动worker时指定并发数:
celery -A proj worker --concurrency=4 # 每个worker启动4个进程
多个worker节点都这样启动,任务就会通过broker的队列平均分发到各个worker进程。
- 队列配置(如果需要更细粒度控制):
from kombu import Exchange, Queue
app.conf.task_queues = (
Queue('default', Exchange('default'), routing_key='default'),
)
app.conf.task_default_queue = 'default'
实际部署时,只要所有worker连接同一个broker(Redis/RabbitMQ),使用相同的队列,broker就会自动以轮询方式把消息分发给各个worker。不需要额外代码。
简单说就是:用默认配置,控制好prefetch,任务自然就平均分配了。
记得有个参数可以设置 worker 一次取几个任务,设置为 1 就好。
具体的需要查文档了。
有个 prefetch_count. 如果这个还觉得不够, 可以参考一下我写的一个任务框架
https://github.com/jiajunhuang/toq
里面有个模式是 sleepy mode, 如果任务过多,就会停止拉取任务
- 给每个 worker 合理的设定–concurrency、–autoscale 参数
2. 同问题 1,有没有其他答案观察 ing
膜拜下大神…
别用 celery 了 用 dask
dask 不是类 pandas 的数据处理包吗…

