关于芹菜,我有几个问题。请帮我。
我们需要在每个芹菜工人中放入项目代码吗?如果是,那么,如果我增加了工作程序的数量并且也在更新代码,那么在所有工作程序实例中更新代码的最佳方法是什么(无需每次都手动将代码推入每个实例)?
在celery worker中使用-Ofair
作为参数,即使设置了PREFETCH_LIMIT=8 or so
也禁止在worker中预取?
重要提示:Rabbitmq经纪人是将任务分配给工人还是工人从经纪人处提取任务?
在系统中拥有多个芹菜工人(子进程数量与核心数量一样)是否有意义?我看到很少有人在一个系统中运行多个芹菜工作者。
要添加到上一个问题,这两种方案之间的性能差异是多少:系统中的单个工作线程(8个核心)或两个工作线程(并发4)
请回答我的问题。预先感谢。
答案 0 :(得分:5)
我们需要在每个芹菜工人中添加项目代码吗?如果是,如果我增加了工作程序的数量并且也在更新代码,那么在所有工作程序实例中更新代码的最佳方法是什么(无需每次都手动将代码推入每个实例)?
是的。芹菜工作者运行您的代码,因此自然需要访问该代码。不过,如何使代码可访问完全取决于您。一些方法包括:
代码更新和工作人员重启作为部署的一部分
如果您在kubernetes吊舱中运行芹菜工人,则可以归结为构建新的docker映像并将您的工人升级到新映像。 Using rolling updates可以在零停机时间内完成。
从存储库安排的同步和工作进程通过广播重新启动
如果您在更传统的环境中运行celery worker,或者由于某些原因不想重建整个映像,则可以使用一些适用于所有worker的中央文件系统,在其中更新文件,例如按计划或通过触发器同步git存储库。重要的是,重新启动所有芹菜工人,以便他们重新加载代码。可以通过remote control完成。
为每个任务动态加载代码
例如,在omega|ml中,我们提供了Lambda样式的无服务器执行
动态加载到工作进程中的任意python脚本。
为避免模块加载和依赖性问题,保留max-tasks-per-child=1
并使用预叉池很重要。虽然这增加了一些开销,但我们却发现,这是一个易于管理的折衷(特别是我们运行机器学习任务,因此在每个任务之后加载脚本和重新启动工作程序的开销很少)
使用celery worker中的-Ofair作为参数,即使已设置PREFETCH_LIMIT = 8左右,也禁止对worker中的预取?
-O fair阻止工作人员执行预取任务,除非存在空闲进程。但是,最近我偶然发现了一个quirk with rate limits。在实践中,我既没有遇到预取也没有速率限制的问题,但是对于任何分布式系统,都需要考虑执行的异步性质的影响(这不是Celery特有的,但适用于所有此类系统)
重要提示:Rabbitmq经纪人是将任务分配给工人还是工人从经纪人处提取任务?
Rabbitmq不了解工人(芹菜支持的任何其他经纪人也不知道)-他们只是维护消息队列。也就是说,是工人从经纪人那里提取任务。
与此有关的一个问题是如果我的工作人员在执行任务时崩溃了,该怎么办。这有几个方面: worker 和 worker进程之间是有区别的。工作者是开始从代理消耗任务的单个任务,它不执行任何任务代码。任务代码由工作进程之一执行。使用prefork池(默认设置)时,仅会重新启动失败的工作进程,而不会影响整个工作进程或其他工作进程。
在一个系统中拥有多个芹菜工人(子进程数量与核心数量一样)是否有意义?我看到很少有人在一个系统中运行多个芹菜工作者。
这取决于您需要运行的工作量的规模和类型。通常,CPU限制的任务应在并发设置不超过内核数的工作器上运行。如果您需要处理的任务多于核心任务,请运行多个工作程序以进行横向扩展。请注意,如果您的受CPU限制的任务一次使用多个内核(例如,在机器学习工作负载/数值处理中通常如此),则是每个任务使用的内核总数,而不是同时运行的任务总数告知您的决定。
要添加到上一个问题,这两种情况之间的性能差异是多少:系统中的单个工作线程(8个核心)或两个工作线程(并发4)
一般来说,最好进行一些测试。例如,如果4个并发运行的任务使用单个节点上的所有内存,则添加另一个工作线程将无济于事。但是如果你有两个队列,例如具有不同的到达速率(例如,一个用于低频率但高优先级的执行,另一种用于高频率但低优先级的到达),这两个节点都可以在同一节点上同时运行,而无需考虑CPU或内存,单个节点就可以。