celery分布式任务队列
Celery 简介
Celery是一个异步任务调度工具,用户使用 Celery 产生任务,借用中间人来传递任务,任务执行单元从中间人那里消费任务。任务执行单元可以单机部署,也可以分布式部署,因此 Celery 是一个高可用的生产者消费者模型的异步任务队列。你可以将你的任务交给 Celery 处理,也可以让 Celery 自动按 crontab 那样去自动调度任务,然后去做其他事情,你可以随时查看任务执行的状态,也可以让 Celery 执行完成后自动把执行结果告诉你。
应用场景
高并发的请求任务。互联网已经普及,人们的衣食住行中产生的交易都可以线上进行,这就避免不了某些时间极高的并发任务请求,如公司中常见的购买理财、学生缴费,在理财产品投放市场后、开学前的一段时间,交易量猛增,确认交易时间较长,此时可以把交易请求任务交给 Celery 去异步执行,执行完再将结果返回给用户。用户提交后不需要等待,任务完成后会通知到用户(购买成功或缴费成功),提高了网站的整体吞吐量和响应时间,几乎不需要增加硬件成本即可满足高并发。
定时任务。在云计算,大数据,集群等技术越来越普及,生产环境的机器也越来越多,定时任务是避免不了的,如果每台机器上运行着自己的 crontab 任务,管理起来相当麻烦,例如当进行灾备切换时,某些 crontab 任务可能需要单独手工调起,给运维人员造成极大的麻烦,有了 Celery ,你可以集中管理所有机器的定时任务,而且灾备无论何时切换,crontab 任务总能正确的执行。
异步任务。 一些耗时较长的操作,比如 I/O 操作,网络请求,可以交给 Celery 去异步执行,用户提交后可以做其他事情,当任务完成后将结果返回用户即可,可提高用户体验。
Celery 的优点
1、纯 Python 编写,开源。这已经是站在巨人的肩膀上了,虽然 Celery 是由纯 Python 编写的,但协议可以用任何语言实现。迄今,已有 Ruby 实现的 RCelery 、node.js 实现的 node-celery 以及一个 PHP 客户端 ,语言互通也可以通过 using webhooks 实现。
2、灵活的配置。默认的配置已经满足绝大多数需求,因此你不需要编写配置文件基本就可以使用,当然如果有个性化地定制,你可以选择使用配置文件,也可以将配置写在源代码文件里。
3、方便监控。任务的所有状态,均在你的掌握之下。
4、完善的错误处理。
5、灵活的任务队列和任务路由。你可以非常方便地将一个任务运行在你指定的队列上,这叫任务路由。
Celery 的架构
消息中间间(Broker):Celery 用消息通信,通常使用中间人(Broker)在客户端和 worker 之前传递,这个过程从客户端向队列添加消息开始,之后中间人把消息派送给 worker。官方给出的实现Broker的工具有:
在实际使用中我们选择 RabbitMQ 或 Redis 作为中间人即可。
执行单元 worker:worker 是任务执行单元,是属于任务队列的消费者,它持续地监控任务队列,当队列中有新地任务时,它便取出来执行。worker 可以运行在不同的机器上,只要它指向同一个中间人即可,worker还可以监控一个或多个任务队列, Celery 是分布式任务队列的重要原因就在于 worker 可以分布在多台主机中运行。修改配置文件后不需要重启 worker,它会自动生效。
任务结果存储backend:用来持久存储 Worker 执行任务的结果,Celery支持不同的方式存储任务的结果,包括AMQP,Redis,memcached,MongoDb,SQLAlchemy等。
Celery 的使用示例:
第一步:创建project(celery_demo),安装redis,eventlet和celery
pip install redis
pip install eventlet
pip install celery
第二步:创建tasks.py和main.py
task.py用于写任务函数,main.py用于执行任务
task.py的代码如下:
import time
from celery import Celery
celery = Celery('tasks', broker='redis://127.0.0.1:6379/0', backend='redis://127.0.0.1.29:6379/0')
@celery.task
def task_demo():
print('任务开始')
time.sleep(5)
print('任务结束')
注意:链接redis数据库时,如果配置了密码的那么连接redis的代码为:
redis://:password@hostname:port/db_number
main.py的代码如下:
from tasks import task_demo
if __name__ == '__main__':
task_demo.delay() # delay()括号中传入的是函数名的参数
第三部:打开pycharm中Terminal,在当前虚拟坏境中输入
celery -A tasks --pool=eventlet worker --loglevel=info
回车:
此时celery已经蓄势待发,进入工作模式,随时等待执行任务。
第四步:在main.py中运行该函数任务
在Terminal中可以观察到celery的执行情况:
redis连接有可能会连接不上,要注意redis.conf文件的配置:
requirepass 123456
如上配置,就是把redis 密码配置为“123456” ,此时连接redis数据库时需要把密码加上。
如果使用的是linux远程连接,需要绑定ip端口,不然有可能连接失败。用cmd打开命令窗口,输入‘ipconfig’
找到ip地址“192.168.0.105”,在redis.conf中允许该ip访问。
bind 192.168.0.105
配置好之后需要重新启动redis:
/usr/bin/redis-server /etc/redis/redis.conf
注意这个是我的重启方式。我的redis-server在/usr/bin/目录下,redis.conf在/etc/redis/目录下