1
saggit 2017-02-27 13:19:43 +08:00
新版本的 settings 名子改了, worker_prefetch_multiplier = 1 试试
|
2
julyclyde 2017-02-27 13:54:53 +08:00
你设置的这是 fetch 的数量啊,不是 execute 的数量
|
3
akmonde OP @saggit 先谢谢这位兄弟,不过我设置了 worker_prefetch_multiplier = 1 并没有起作用。
另外,我看到网上有解释,“ celery 中的一个 worker 其实是代表一个进程池,一个进程池是由一个父进程和多个子进程组成, 貌似父进程不干事,只用于分配 task ,子进程数默认是 CPU 核数” 故而我也试着配置了 CELERYD_MAX_TASKS_PER_CHILD = 2 ,但是貌似没起作用。 还是每个 worker 分配 start 了好几个 task , RECEVED 也一大把。 另外,我想问问大家怎么一次性,把那么多起来的 task 全部结束掉,每次 terminate 好多次。 |
5
julyclyde 2017-02-27 14:04:52 +08:00 1
|
6
akmonde OP @julyclyde 非常感谢兄弟,确实有效,要是能直接写到配置里就更好了, hhhh
另外兄弟知道把那么 start 和 receive 后 task 全部结束掉么? 我每次都是直接 ctrl+C 把 worker 结束掉,因为用的 redis 作中间件,最后还会手动清理 redis 的缓存内容,不然它还会一直运行下去。 不过这样好像不太正规,也有点 bug 。 |
7
julyclyde 2017-02-27 17:42:14 +08:00
犯不着写配置文件里啊,反正你也得从 celery worker 命令行启动,多个-c 参数的小事而已
听不懂“把那么 start 和 receive 后 task 全部结束掉” |
8
akmonde OP @julyclyde 我的意思是:前台已经发了任务,存在了中间件( redis ),然后后台取了任务,有的已经 start ,有的还在 receive 状态,如何把这些废弃的任务全部结束掉。
我直接把那些 worker ctrl+c 掉的话,重新启动 worker 时,那些被废弃的任务还会继续跑。 |
9
julyclyde 2017-02-27 21:20:54 +08:00
这细节动作我就没注意观察过了
诶按说 redis 作为队列的话,取出来是不会放回去的啊? |
10
maemo 2017-02-27 21:45:39 +08:00
@akmonde 你有用 multi 方式起 worker 吗,如果有的话,直接把起 worker 的命令中的 start 换成 stop 。 要清理废弃的任务的话,可以用 celery purge -Q queuename, 具体用法可以查看 celery purge --help
|
11
akmonde OP @maemo 并没有用 multi 喔,至于您说的 queuename 是 task 名么?类似于“ e1e10f99-fb7b-42a4-b627-7ea0e74daf90 ”?我那边用 flower 控制的,但也没有看见批量清除的法子,有点头疼。。
|
12
akmonde OP @julyclyde 没,我猜是放到了 redis 里面的,清除 redis 后过会儿会结束。
但清除 redis 后再启动时, celery 还会调度一会儿 task ,这部分不知道是存在哪儿的,我一直很奇怪。 |
13
xnightsky 2017-02-27 23:50:41 +08:00
看配置项`result_backend `, task 信息存在 result_backend 配置对应位置,还有`result_expires `配置项,所有 task 默认存 1 天
|
14
xnightsky 2017-02-27 23:51:30 +08:00
不过 celelry 命令行有参数能干掉所有任务
|
16
xnightsky 2017-02-28 01:21:29 +08:00
`celery -h` 其他配置项就不说了
看一下命令行说明 ```` celery purge 返回 WARNING: This will remove all tasks from queue: celery. There is no undo for this operation! (to skip this prompt use the -f option) Are you sure you want to delete all tasks (yes/NO)? ```` 这是我本机的提示 |
17
xnightsky 2017-02-28 01:23:01 +08:00
不知他能否干掉已经被 fetch 的命令,需要你排查
|
19
Stony 2017-08-03 00:36:30 +08:00 2
http://docs.celeryproject.org/en/latest/userguide/configuration.html
参数配置都在这里,新旧配置的 key 对照表也有。 CELERYD_PREFETCH_MULTIPLIER = n worker_prefetch_multiplier = n 这个是任务预取功能,就是每个工作的进程/线程/绿程在获取任务的时候,会尽量多拿 n 个,以保证获取的通讯成本可以压缩,在每个任务很短(明显小于 1 秒)情况下,是值得调大的,而且推荐是 2 的幂。0 表示尽可能多拿。如果 1 个都不想多拿,那么除了设置 1 外,还需要 设置 task_acks_late 为 true,如果你的任务不是幂等(可以重复调用)的话,可能会有问题。详细解释参考: http://docs.celeryproject.org/en/latest/userguide/optimizing.html task_acks_late = True worker_prefetch_multiplier = 1 CELERYD_MAX_TASKS_PER_CHILD = n worker_max_tasks_per_child = n 这个表示每个工作的进程/线程/绿程 在执行 n 次任务后,主动销毁,之后会起一个新的。主要解决一些资源释放的问题。 CELERY_TASK_RESULT_EXPIRES = s result_expires = s 这个表示保存任务结果的时长,这个时间会被设置到 redis 里面(假设 backend 是 redis ),如果抓取数据量大的话,是可以缩短保存的时间,节省 backend 的资源( redis 主要是内存)消耗,默认是 24 小时( 86400 ),单位是秒。 ===分割线=== 已经 fetch 的任务,要么等执行完毕,要么等 kill 掉。要注意 soft kill 和 hard kill 的区别,没记错的话是 TERMINAL 和 kill -9 的区别。soft kill 会执行完当前的 task,但是,prefetch 的会丢失。在 pycharm 里,我第一次 ctrl+c 是软 kill,可能会等上一会儿,第二次 ctrl+c 是硬 kill,直接停掉进程。 没有 fetch 的任务可以 purge 清理调队列中的。 根据选择的 pool 类型不同,可以有 solo (单进程) prefork (进程池) threading (线程池) gevent (协程池)和 eventlet (协程池)。4.x 好像废弃了线程池,主要的原因我猜可能和 GIL 有关。进程池比较耗内存,好处是所有工作线程资源都是隔离的,如果配置动态数量的挺好用。协程池 则对于 IO 密集型工作比较有优势。所有的并发数量默认是 cpu core 的数量,4 核就是 4,可以根据实际情况调大。 |
20
akmonde OP @Stony 非常感谢您,很详细,这帖子我差点都忘了。。另外,我想请教下您,如果想批量 kill 一批机器的 task,应该咋弄,我通常是直接 grep celery 的所有进程,然后 kill -9。
但是这样就有个毛病,我批量 kill 集群中的 task 时会出现问题,只有一台一台机器去手动操作。 另外,您说如果 celery 卡住的时候,重启所有 pool 有用么?话说我以前配置了 pool 的安全选项,还是不能在 flower 直接重启。 |
21
mengdodo 2018-11-15 11:23:49 +08:00 1
@akmonde
#查看 celery 启动的 work 进程 pid ps aux | grep celery #批量 kill 所有的 celery 生成的 work 方法 1 ps auxww | grep 'worker -l info' | awk '{print $2}' | xargs kill -9 #批量 kill 掉 celery 的 work 方法 2 详细文档: https://celery.readthedocs.io/en/latest/userguide/workers.html#stopping-the-worker pkill -9 -f 'celery -A [项目名] worker' |
23
louyuguang 2019-01-14 11:46:57 +08:00
@Stony 兄弟,你的 task_acks_late 这个参数对我帮助太大了,这个问题我找了两个礼拜。
因为我的一个 task 可能要执行 10s~600s 不等,我的 worker 同时只能执行一个 task。所以我不希望任何一个 worker 在执行一个任务的时候,再接收其他任务(除非所有 worker 都在执行任务。) |