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