Celery介绍和使用

思考:

  • 消费者取到消息之后,要消费掉(执行任务),需要我们去实现。
  • 任务可能出现高并发的情况,需要补充多任务的方式执行。
  • 耗时任务很多种,每种耗时任务编写的生产者和消费者代码有重复。
  • 取到的消息什么时候执行,以什么样的方式执行。

结论:

  • 实际开发中,我们可以借助成熟的工具Celery来完成。
  • 有了Celery,我们在使用生产者消费者模式时,只需要关注任务本身,极大的简化了程序员的开发流程。

1. Celery介绍

  • Celery介绍:

    • 一个简单、灵活且可靠、处理大量消息的分布式系统,可以在一台或者多台机器上运行。
    • 单个 Celery 进程每分钟可处理数以百万计的任务。
    • 通过消息进行通信,使用消息队列(broker)客户端消费者之间进行协调。
  • 安装Celery:

    $ pip install -U Celery
    
  • Celery官方文档

2. 创建Celery实例并加载配置-rabbitmq

1.定义Celery包 初始化

2.创建Celery实例

celery_tasks.main.py

# celery启动文件
from celery import Celery

# 创建celery实例
celery_app = Celery('meiduo')

3.加载Celery配置

celery_tasks.config.py

# 指定消息队列的位置
broker_url= 'amqp://guest:guest@192.168.186.134:5672'

celery_tasks.main.py

# celery启动文件
from celery import Celery

# 创建celery实例
celery_app = Celery('meiduo')
# 加载celery配置
celery_app.config_from_object('celery_tasks.config')

3. 定义发送短信任务

1.注册任务:celery_tasks.main.py

# Celery 的入口

from celery import Celery
# 为celery使用django配置文件进行设置
import os
# 如果你需要使用到django,需要加载django模块
if not os.getenv('DJANGO_SETTINGS_MODULE'):
    os.environ['DJANGO_SETTINGS_MODULE'] = 'meiduo_mall.settings.dev'

# 创建celery实例
celery_app = Celery('meiduo')

# 加载配置
celery_app.config_from_object('celery_tasks.config')

# 任务
celery_app.autodiscover_tasks([
    'celery_tasks.sms',
])

2.定义任务:celery_tasks.sms.tasks.py

# 定义任务
import logging

from celery_tasks.sms.yuntongxun.SendTemplateSMS import CCP
from . import constants
from celery_tasks.main import celery_app

# bind:保证task对象会作为第一个参数自动传入
# name:异步任务别名
# retry_backoff:异常自动重试的时间间隔 第n次(retry_backoff×2^(n-1))s
# max_retries:异常自动重试次数的上限
# 使用装饰器装饰异步任务,保证celery识别任务
logger = logging.getLogger('celery_sms')


@celery_app.task(bind=True, name='send_sms_code', retry_backoff=3)
def send_sms_code(self, mobile, sms_code):
    """
    发送给短信验证码异步任务
    :param self:
    :param mobile: 手机号码
    :param sms_code: 短信验证码
    :return: 成功 1 失败 -1
    """
    # # 发送短信
    # send_ret = CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60],
    #                                    constants.SEND_SMS_TEMPLATE_ID)
    # return send_ret
    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

constants.py

# 图形验证码有效期,单位:秒
IMAGE_CODE_REDIS_EXPIRES = 300

# 短信验证码有效期,单位:秒
SMS_CODE_REDIS_EXPIRES = 300

# 短信模板
SEND_SMS_TEMPLATE_ID = 1

# 60s内是否重复发送的标记
SEND_SMS_CODE_INTERVAL = 60

4. 启动Celery服务

$ cd ~/projects/meiduo_project/meiduo_mall
$ celery -A celery_tasks.main worker -l info
  • -A指对应的应用程序, 其参数是项目中 Celery实例的位置。
  • worker指这里要启动的worker。
  • -l指日志等级,比如info等级。

5. 调用发送短信任务

# 发送短信验证码
# 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)

6. 补充celery worker的工作模式

  • 默认是进程池方式,进程数以当前机器的CPU核数为参考,每个CPU开四个进程。
  • 如何自己指定进程数:celery worker -A proj --concurrency=4
  • 如何改变进程池方式为协程方式: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

使用redis中间件配置

先安装和配置好
django中安装和配置redis

修改
celery_tasks.config.py

# 指定消息队列的位置
broker_url = "redis://192.168.186.134/10"