Celery
1. Celery介绍
-
Celery介绍:
- 一个简单、灵活且可靠、处理大量消息的分布式系统,可以在一台或者多台机器上运行。
- 是一个基于生产者消费者设计模式的实现异步消息处理的系统
- 单个 Celery 进程每分钟可处理数以百万计的任务。
- 通过消息进行通信,使用
消息队列(broker)
在客户端
和消费者
之间进行协调。
-
安装Celery:
$ pip install -U Celery
2. Celery的使用
2.1 定义启动文件main.py
# 导入Celery from celery import Celery # 创建Celery实例 celery_app = Celery("meido")
2.2 定义配置文件config.py,并在启动文件中加载配置
# 指定消息队列的位置 broker_url= 'redis://127.0.0.1:6379/10'
-
broker_url为固定写法
启动文件中添加加载配置文件的代码:
# 导入Celery from celery import Celery # 创建Celery实例 celery_app = Celery("meido") # 加载配置 celery_app.config_from_object("celery_tasks.config")
2.3 定义任务,并在启动文件中注册任务
创建sms包并定义tasks.py文件:
在tasks.py文件中定义任务:
from celery_tasks.sms.yuntongxun.ccp_sms import CCP from . import constants from celery_tasks.main import celery_app # name:异步任务别名 @celery_app.task(name='ccp_send_sms_code') def ccp_send_sms_code(mobile, sms_code): """ 发送短信异步任务 :param mobile: 手机号 :param sms_code: 短信验证码 :return: 成功0 或 失败-1 """ send_ret = CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], constants.SEND_SMS_TEMPLATE_ID) return send_ret
- 文件名tasks.py为固定写法
-
@celery_app.task对应celery实例的task装饰器
启动文件main.py中注册任务
# 导入Celery from celery import Celery # 创建Celery实例 celery_app = Celery("meido") # 加载配置 celery_app.config_from_object("celery_tasks.config") # 注册任务 celery_app.autodiscover_tasks(["celery_tasks.sms"])
2.4 启动Celery服务
虚拟环境下:
cd ~/projects/meiduo_project/meiduo_mall
celery -A celery_tasks.main worker -l info
window系统下,可能出现消息不消费情况,此时,需要使用如下命令启动:
celery -A celery_tasks.main worker --pool=solo -l info
说明:
-A
指对应的应用程序, 其参数是项目中 Celery实例的位置。worker
指这里要启动的worker。-l
指日志等级,比如info
等级。
启动日志如下:
(py3_django) D:\work\meiduo-project\meiduo_mall>celery -A celery_tasks.main worker --pool=solo -l info -------------- celery@DESKTOP-OT3BAUF v5.0.5 (singularity) --- ***** ----- -- ******* ---- Windows-10-10.0.18362-SP0 2021-03-08 22:58:31 - *** --- * --- - ** ---------- [config] - ** ---------- .> app: meido:0x16406930a90 - ** ---------- .> transport: redis://127.0.0.1:6379/10 - ** ---------- .> results: disabled:// - *** --- * --- .> concurrency: 4 (solo) -- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker) --- ***** ----- -------------- [queues] .> celery exchange=celery(direct) key=celery [tasks] . ccp_send_sms_code [2021-03-08 22:58:31,180: INFO/MainProcess] Connected to redis://127.0.0.1:6379/10 [2021-03-08 22:58:31,180: INFO/MainProcess] mingle: searching for neighbors [2021-03-08 22:58:32,211: INFO/MainProcess] mingle: all alone [2021-03-08 22:58:32,211: INFO/MainProcess] celery@DESKTOP-OT3BAUF ready.
2.5 异步调用,发送任务给Celery
# 发送短信验证码 # CCP().send_template_sms(mobile,[sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], constants.SEND_SMS_TEMPLATE_ID) # Celery异步发送短信验证码 ccp_send_sms_code.delay(mobile, sms_code)
说明:
- ccp_send_sms_code为Celery任务定义中的方法,此处使用.delay调用完成异步发送任务给Celery
控制台显示的Celery服务接收任务并执行的日志:
(py3_django) D:\work\meiduo-project\meiduo_mall>celery -A celery_tasks.main worker --pool=solo -l info -------------- celery@DESKTOP-OT3BAUF v5.0.5 (singularity) --- ***** ----- -- ******* ---- Windows-10-10.0.18362-SP0 2021-03-08 22:58:31 - *** --- * --- - ** ---------- [config] - ** ---------- .> app: meido:0x16406930a90 - ** ---------- .> transport: redis://127.0.0.1:6379/10 - ** ---------- .> results: disabled:// - *** --- * --- .> concurrency: 4 (solo) -- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker) --- ***** ----- -------------- [queues] .> celery exchange=celery(direct) key=celery [tasks] . ccp_send_sms_code [2021-03-08 22:58:31,180: INFO/MainProcess] Connected to redis://127.0.0.1:6379/10 [2021-03-08 22:58:31,180: INFO/MainProcess] mingle: searching for neighbors [2021-03-08 22:58:32,211: INFO/MainProcess] mingle: all alone [2021-03-08 22:58:32,211: INFO/MainProcess] celery@DESKTOP-OT3BAUF ready. [2021-03-08 22:59:23,983: INFO/MainProcess] Received task: ccp_send_sms_code[9734a0d8-312d-478c-a9a7-a5faa090c7cd] [2021-03-08 22:59:24,295: WARNING/MainProcess] result [2021-03-08 22:59:24,295: WARNING/MainProcess] {'statusCode': '000000', 'templateSMS': {'smsMessageSid': '3430d32c8b77402da44a220994c1abb7', 'dateCreated': '202103 08225903'}} [2021-03-08 22:59:24,295: WARNING/MainProcess] 0 [2021-03-08 22:59:24,295: INFO/MainProcess] Task ccp_send_sms_code[9734a0d8-312d-478c-a9a7-a5faa090c7cd] succeeded in 0.3129999999998745s: 0
2.6 celery任务失败重试机制
# bind:设置为True,实现当前任务对象task会作为第一个参数(self)自动传入 # name:异步任务别名 # retry_backoff:用于计算异常自动重试的时间间隔:第n次间隔时间:(retry_backoff×2^(n-1))s # max_retries:异常自动重试次数的上限 @celery_app.task(bind=True, name='ccp_send_sms_code', retry_backoff=3) def ccp_send_sms_code(self, mobile, sms_code): """ 发送短信异步任务 :param mobile: 手机号 :param sms_code: 短信验证码 :return: 成功0 或 失败-1 """ try: send_ret = CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], constants.SEND_SMS_TEMPLATE_ID) except Exception as e: logger.error(e) # 有异常自动重试三次 raise self.retry(exc=e, max_retries=3) if send_ret != 0: # 有异常自动重试三次 raise self.retry(exc=Exception('发送短信失败'), max_retries=3) return send_ret
3. 补充celery worker的工作模式
- 默认是进程池方式,进程数以当前机器的CPU核数为参考,每个CPU开四个进程。
- 如何自己指定进程数: celery worker -A proj --concurrency=4 ,这里--concurrency指定开的进程数,也可简写 -c 来指定
- 如何改变进程池方式为协程方式:先安装eventlet模块,然后执行 celery worker -A proj --concurrency=1000 -P eventlet -c 1000
# 安装eventlet模块 $ pip install eventlet # 启用 Eventlet 池 $ celery -A celery_tasks.main worker -l info -P eventlet -c 1000
- 这里指定了开1000个协程
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?