celery执行池概览

执行池概念

当运行类似 如下命令启动一个celery进程时,其实启动的是一个管理进程,此进程不处理实际的任务,而是产生的子进程或线程 去处理具体任务;那么这些 子进程或线程 在一起就叫做 执行池;

celery worker --app=worker.app

执行池的大小(子进程或线程的个数) 决定了 celery可以并发执行任务的个数;如果想尽可能快和多的执行任务,那么 增加执行池的大小 是个可以考虑的解决方案;

选择不同的执行池工作方式

Prefork

celery默认的执行池工作方式,是多进程的执行池,一般在 计算密集型任务中使用,能充分利用cpu多核; 如果不指定 –concurrency(并发进程个数)参数,则无论什么执行池都是尽可能多的使用cpu的核数;

Solo

这种执行池有点特殊,因为此模式在处理任务时 直接在 管理进程中进行; 不是基于进程或线程的工作模式; 也就是一直只有一个 消费者 在处理任务;上个任务不结束,则下个任务就会阻塞; 但是在微服务中 比如 在使用k8s 进行 docker部署时,可以使用此模式,这样 k8s直接通过观察启动多少个docker容器 就能知道启动了多少个celery消费者;

此模式即使指定--concurrency(并发数) 参数值 也没有任何意义;

Eventlet/Gevent

2个都是基于协程 的执行池,一般在 IO密集型任务中使用,如频繁的网络请求,数据库操作等等;

gevent是对eventlet的高级封装,一般使用时 用 gevent,因为此包有monkey.patch_all()方法将 所有能转为协程的地方都转为协程,从而增加处理能力;

此模式指定--concurrency(并发数) 参数值可以比CPU核数多,理论上 只要内存不爆,套接字够用,就可以增加;

实际使用

需求: 多任务 从mysql查询将 数据导入到mongo中;且任务间没有依赖关系

实现:使用celery+gevent实现任务并发;

用法:此任务为IO密集型任务(查询mysql,并发导入mongo[业务端只需将数据发送给mongo,其内部会实现并发处理]),且每个任务内存消耗均有一些;因此使用gevent,且设置并发数不能过多,否则可能出现内存不足情况;

部分代码如下:

"""
没有 celery定时任务,所以不需要 心跳服务
此次使用 基于协程的 gevent作为 执行池(execution pool);因为 瓶颈在于 同步到mongo的IO上;
本地测试时 可将 --pool=gevent 改为 --pool=solo 使worker顺序消费任务方便debug;
"""
from gevent import monkey

# 使用gevent注意调用此方法
monkey.patch_all()
import os
from app import create_app
from app.core import celery

app = create_app()

if __name__ == '__main__':
    os.environ["START_METHOD"] = "worker"
    # 本地开发调试时,注意将 --pool 值改为 solo
    celery.start(
        ["celery", "-A", "worker.celery", "worker", "--pool=gevent", "--loglevel=INFO", "-E", "-n", 'node_name_xxx',
         "-Q", "queue_name_xxx"])

相关链接

Celery Execution Pools

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用 Celery 的 beat scheduler 配合 crontab 表达式来实现随机时间执行任务。具体步骤如下: 1. 在 Celery 中配置 beat scheduler,可以参考 Celery 文档中的介绍。 2. 在 Celery 的配置文件中定义一个 crontab 表达式,如下所示: ``` from celery.schedules import crontab celery_beat_schedule = { 'random_task': { 'task': 'your_task_name', 'schedule': crontab( minute='*/5', # 每隔 5 分钟执行一次 hour='*', # 每小时都执行 day_of_week='*', # 每天都执行 day_of_month='*', # 每个月都执行 month_of_year='*', # 每年都执行 minute=random.randint(1, 59), # 随机分钟数 ), }, } ``` 上面的配置中,我们设置了一个名为 random_task 的任务,使用 crontab 表达式定义了每隔 5 分钟执行一次,并且随机选择一个分钟数执行。这样就可以实现随机时间执行任务的效果了。 3. 在 Celery 中启动 beat scheduler,让其按照我们定义的配置定时执行任务。 ``` celery -A your_celery_app beat -s /path/to/celerybeat-schedule ``` 在启动 beat scheduler 时,需要指定一个状态文件,用来保存任务的执行状态,以便下一次启动时能够恢复之前的状态。 4. 在你的代码中定义一个名为 your_task_name 的任务,实现具体的逻辑。 ``` from celery import Celery app = Celery('your_celery_app') @app.task def your_task_name(): # TODO: 实现具体的逻辑 ``` 在上面的代码中,我们使用 Celery 的装饰器 @app.task 来定义一个名为 your_task_name 的任务,然后在函数体中实现具体的逻辑。当 beat scheduler 按照我们定义的时间执行任务时,就会调用这个函数来执行具体的逻辑了。 以上就是实现随机时间执行任务的大致步骤,你可以根据自己的需求进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值