一、异步任务
异步任务是web开发中一个很常见的方法。对于一些耗时耗资源的操作,往往从主应用中隔离,通过异步的方式执行。
运用场景:注册的功能,在用户使用邮箱注册成功之后,需要给该邮箱发送一封激活邮件。如果直接放在应用中,则调用发邮件的过程会遇到网络IO的阻塞,比较好的处理方式则是使用异步任务,将发邮件从主业务中解耦出来,应用在业务逻辑中触发一个异步任务。
二、生产者消费者模式
生产者生成消息,缓存到消息队列中,消费者读取消息队列中的消息并执行。
生产者消费者模式面向过程的一种编程模式。在实际的软件开发过程中,经常会碰到如下场景:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类、函数、线程、进程等)。产生数据的模块,就形象地称为生产者;而处理数据的模块,就称为消费者。
三、celery
celery是基于python实现的一个异步任务的调度工具,同时还是一个任务队列,主要用于处理耗时的任务。
celery本身不含消息服务,需要依赖一个消息队列MQ来来传递任务,客户端代码只需要向MQ中派发任务,Celery进程就可以从MQ中读取消息并派发给worker,从而达到了客户端程序与Celery进程解耦的效果。而且Celery进程并不需要监听任何端口,减少了配置的复杂性。目前,Celery支持的消息服务有RabbitMQ、Redis甚至是数据库,当然Redis应该是最佳选择。
(1)celery架构
celery架构由三个模块组成:消息中间件(message broker),任务执行单元(worker)和任务执行结果存储(task result store)组成。
消息中间件(Broker): 消息中间人,是任务调度队列,是一个独立的服务,是一个生产者消费者模式,生产者把任务放入队列中,消费者(worker)从任务队列中取出任务执行,任务的执行可以按照顺序依次执行也可以按照计划时间进行。但是Broker本身不提供队列服务,所以要集成第三方队列,推荐使用RatbbitMQ或Redis.
任务执行单元(worker):即执行任务的程序,可以有多个并发。它实时监控消息队列,获取队列中调度的任务,并执行它。
任务执行结果存储(task result store):由于任务的执行同主程序分开,如果主程序想获取任务执行的结果,就必须通过中间件存储。同消息中间人一样,存储也可以使用RabbitMQ、Redis;另外,假如不需要保存执行的结果也可以不配置这个模块。
(2)celery特点
- 简单:Celery 易于使用和维护,并且它不需要配置文件
- 高可用性:倘若连接丢失或失败,进程和客户端会自动重试,并且通过主/主或主/从方式复制来提高可用性
- 快速:单个 Celery 进程每分钟可处理数以百万计的任务,而保持往返延迟在亚毫秒级
- 灵活:Celery 几乎所有部分都可以扩展或单独使用。可以自制连接池、序列化、压缩模式、日志、调度器、消费者、生产者、自动扩展、中间人传输或更多。
(3)工作原理
它的基本工作就是管理分配任务到不同的服务器,并且取得结果。至于说服务器之间是如何进行通信的?这个Celery本身不能解决。所以,RabbitMQ作为一个消息队列管理工具被引入到和Celery集成,负责处理服务器之间的通信任务。和rabbitmq的关系只是在于,celery没有消息存储功能,他需要介质,比如rabbitmq、redis、mysql、mongodb 都是可以的。
(4)celery应用
安装:
- 用pip安装:$ pip install -U Celery
- 用easy_install 安装:$ easy_install -U Celery
- 捆绑式安装:$ pip install celery[librabbitmq] 或者 $ pip install
celery[librabbitmq,redis,auth,msgpack]。
步骤:
①执行任务单元 task.py
task.py中
from celery import Celery
import time
# broker和backend都设置为redis
my_task = Celery('task',broker='redis://127.0.0.1:6379/1',
backend='redis://127.0.0.1:6379/2')
# 任务执行单元
@my_task.task
def func1(x,y):
time.sleep(10)
return x + y
② 派送任务 handle.py
from task import func1
res = func1.delay(2,4) # 用delay去向执行单元派送任务并传参
print(res.id)
③先运行worker,让他处于ready状态,如果有数据就可以直接处理数据:
celery worker -A task -l INFO
# -A 指定worker所在的Celery app的文件名,就是task
# -l 是日志打印的级别
# -c 10 可以同时开启10个worker处理
# 运行结果
[tasks]
. task.func1
[2019-05-20 16:37:28,752: INFO/MainProcess] Connected to redis://127.0.0.1:6379//
[2019-05-20 16:37:28,768: INFO/MainProcess] mingle: searching for neighbors
[2019-05-20 16:37:29,797: INFO/MainProcess] mingle: all alone
[2019-05-20 16:37:29,841: INFO/MainProcess] celery@hjj-virtual-machine ready.
④运行我们的发送命令的 handle.py
python3 handle.py
参考:
https://www.jianshu.com/p/1840035cb510
https://www.cnblogs.com/pythonlyz/p/10325640.html
https://www.cnblogs.com/jimmyhe/p/10895742.html