我把在v2上发的帖子下面的评论摘抄下来
原帖:https://www.v2ex.com/t/593748#r_7793688
两个说的比较详细的回答:
回答1:
一个工厂(worker)有一个员工(单进(线)程),为了提高效率,请多了几个员工一起工作(单 worker 多进程)
为了防止这个工厂断电无法工作,那么多建了几个工厂,每个工厂有多个员工(多 worker 多进程)
实际上都是在实现并发
单 worker 可以开 n 个进程进行工作,一个 worker 挂了往往所有进程都会挂掉
多 worker 假设为 m 个,可以理解为分布式,为了防止一个 worker 挂了(或者性能不足等原因),导致无法工作
那么能够并发处理的任务数量理论上为 m * n
一般 worker(不仅 celery,很多设计都是这样)指一个调度主进程 + 多个子工作进程
一个 worker 有什么缺点:
- 如果这个 worker 的主进程挂了,那么整个任务系统都崩了。
- 再往深点,如果你服务端 master 发送的任务速度很快,远大于 worker 主进程去分发任务的速度,可能会影响效率(但这种情况很少,而且这种框架一般都是容忍延迟的)
- 部署 worker 这台机器挂了,那么你的任务系统都崩了
- 这台机器的资源(cpu,内存,IO 等)无法满足你的需求
比较常见的是在不同机器部署多个 worker
在不考虑机器和进程挂掉但情况,其实一个 worker 开 8 个进程和 2 个 worker 每个开 4 个进程的效率是接近的
回答2:
celery 里面的-c 参数指定的是并发度,而-P 参数指定并发的实现方式,有 prefork (default)、eventlet、gevent 等,prefork 就是多进程的方式去实现并发。
你理解的多 worker 对应到多个进程,每个 worker (进程)自己内部还能并发是 gunicorn 的方式。gunicorn 的-w 参数指定有几个 worker (即几个进程),-k 参数指定每个 worker 的并发方式,可以是多线程或者多协程,也可以指定为 sync,表示 worker 是同步的,即不能并发。
比如 gunicorn 的-w 10 -k sync 和 celery 的-c 10 -P prefork 是等价的,都是创建 10 个进程去做并发,并发度最高就是 10。
再例如 celery 的-c 10 -P gevent 表示创建 10 个 gevent 协程去做并发,最高并发度也是 10。而 gunicorn 的-w 10 -k gevent,表示的是创建 10 个进程,且每个进程都是 gevent 异步的,这个并发度就很高了。