celery异步框架

Celery异步任务处理

1. Celery介绍

==Celery安装== celery,分布式异步任务队列 eventlet,并发网络库 gevent 协程库

pip install celery==4.4.7

pip install eventlet==0.26.1

celery异步框架_第1张图片

==Celery介绍== Celery中文手册 Celery 是一个 基于python的分布式异步任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, 举几个实例场景:

  • 异步任务:将==耗时==的操作任务提交给Celery异步执行,比如发送短信/邮件、消息推送、音频处理等等

  • 做一个定时任务,比如每天定时执行爬虫爬取指定内容

  • 还可以使用celery实现简单的分布式爬虫系统等等

Celery 在执行任务时需要通过一个==消息中间件==(Broker)来接收和发送任务消息,以及存储任务结果

Celery有以下优点:

  • 简单:Celery 易于使用和维护,并且它 不需要配置文件 ,并且配置和使用还是比较简单的

  • 高可用:当任务执行失败或执行过程中发生连接中断,celery 会自动尝试重新执行任务

  • 快速:单个 Celery 进程每分钟可处理数以百万计的任务,而保持往返延迟在亚毫秒级

  • 灵活: Celery 几乎所有部分都可以扩展或单独使用,各个部分可以自定义。

==celery核心==

1、Task

任务(Task)就是你要做的事情,例如一个注册流程里面有很多任务,给用户发验证邮件就是一个任务,这种耗时任务可以交给Celery去处理,还有一种任务是定时任务,比如每天定时统计网站的注册人数,这个也可以交给Celery周期性的处理。

2、Broker

Broker 的中文意思是经纪人,指为市场上买卖双方提供中介服务的人。在Celery中它介于生产者和消费者之间经纪人,这个角色相当于数据结构中的队列。例如一个Web系统中,生产者是处理核心业务的Web程序,业务中可能会产生一些耗时的任务,比如短信,生产者会将任务发送给 Broker,就是把这个任务暂时放到队列中,等待消费者来处理。消费者是 Worker,是专门用于执行任务的后台服务。Worker 将实时监控队列中是否有新的任务,如果有就拿出来进行处理。Celery 本身不提供队列服务,一般用 Redis 或者 RabbitMQ 来扮演 Broker 的角色

3、Worker

Worker 就是那个一直在后台执行任务的人,也称为任务的消费者,它会实时地监控队列中有没有任务,如果有就立即取出来执行。

4、Beat

Beat 是一个定时任务调度器,它会根据配置定时将任务发送给 Broker,等待 Worker 来消费。

5、Backend

Backend 用于保存任务的执行结果,每个任务都有返回值,比如发送邮件的服务会告诉我们有没有发送成功,这个结果就是存在Backend中,当然我们并不总是要关心任务的执行结果。

官方文档: 简介 - Celery 中文手册

2. Celery简单使用

==创建worker==

  1. 创建一个文件laufing.py,内部编写如下代码

​
#实例化对象
from celery import Celery
​
# 第一个参数worker name 
# broker 代理,消息中间件
app = Celery("myworker", broker="redis://:laufing@localhost:6379/4")
#也可以app.conf.broker_url = "xxxx"
​
#创建任务函数
@app.task
def task1():
    print("正在执行任务...")
  1. 前台启动worker进程。 在cmd 命令行输入如下:

​
# windows 下需要加-P eventlet  或者 -P gevent
#因为celery 4.x 对window支持的不太好
celery -A laufing worker --loglevel=info -P eventlet
​
#linux
celery -A laufing worker -l info

celery异步框架_第2张图片

  1. 模拟django发送任务

ipython中模拟发送任务:在laufing.py的同级目录打开一个cmd命令行。 celery异步框架_第3张图片

  1. 任务在worker进程中执行。 celery异步框架_第4张图片

3. Celery存储任务结果

  1. 创建一个laufing.py文件,并创建worker

from celery  import Celery
​
app = Celery("worker2", broker="redis://:laufing@localhost:6379/4", backend="redis://:laufing@localhost:6379/5")
​
@app.task
def task1(a, b):
    print("简单求和")
    return a + b
​
@app.task
def task2(a, b):
    print("2-s后求和")
    time.sleep(20)
    return a + b
  1. 前台启动worker

#window
celery -A laufing worker -l info -P eventlet
  1. 发送任务,并获取结果 ipython中测试如下:

from laufing import task1, task2
​
r1 = task1.delay(3, 5)  # 发送任务
r1.result
​
r2 = task2.delay(4, 7) #发送任务,并立即执行下一行,不会阻塞
r2.result   # worker来执行task,返回结果后才可以拿到

分布式的worker:只需在多个主机上启动该laufing下的worker即可, 每一个worker进程都是并发处理任务

4. celery异步发送短信

  1. 在django项目主应用下创建celery.py文件,配置以下内容:

# celery.py文件
import os
from celery import Celery
from django.conf import settings
​
# 为celery配置环境变量,识别和加载django的配置文件
# 因为worker是脱离django启动的,且依赖其配置
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mdpro.settings') # 主应用
​
# 创建celery实例
app = Celery('mdpro')
​
# 指定celery消息队列的配置
app.config_from_object('mdpro.config', namespace='CELERY')
#也可以app.conf.update(BROKER_URL="XXX")
​
# 从所有的django-app中加载任务
app.autodiscover_tasks(settings.INSTALLED_APPS) 
​
  1. 在django项目主应用mdpro下创建config.py文件,配置以下内容:

# 消息中间人broker设置
broker_url = 'redis://127.0.0.1:6379/15'  #不能写localhost
# 结果存储设置
result_backend = 'redis://127.0.0.1:6379/14'
​
  1. 在django项目其他应用下,这里是users,创建tasks.py

# tasks.py
from ronglian_sms_sdk import SmsSDK
from mdpro.celery import app
 
import json
import random
​
accId = '8a216da8757784cd017586e2a0280446'
accToken = '92fbee01e5474904a437b062ea43baf4'
appId = '8a216da8757784cd017586e2a0f4044c'
​
​
@app.task
def send_message(phone, msg_code):
    sdk = SmsSDK(accId, accToken, appId)
    tid = '1'  # 容联云分配的一个测试短信验证码模版
    mobile = phone  # 接收短信的手机号
    datas = (msg_code, '5')
    resp = sdk.sendMessage(tid, mobile, datas)
    resp_json = json.loads(resp)
    return resp_json
​
  1. 视图中发送异步任务

class GenerateVerifyCode(APIView):
    """
    生成手机号验证码
    """
    def post(self, request):
        code_id = request.data.get('code_id')
        phone = request.data.get('phone')
        msg_code = '%06d' % random.randint(0, 1000000)
        #发送任务
        res = send_message.delay(phone, msg_code)  # 0或者 11111
        print("异步队列的响应", res) #
        sms_redis.set(code_id, msg_code, ex=300)
        return Response({'msg': 'OK', 'code': 200})

启动celery

# windows系统下启动
celery -A mdpro worker -l info -P eventlet
​
# mac下启动,
celery -A mdpro worker -l info

​​​​​​​

你可能感兴趣的:(服务器,数据库)