celery
一、celery是什么
Celery是一个简单、灵活且可靠的,处理大量消息的分布式系统专注于实时处理的异步任务队列,同时也支持任务调度
二、celery实现原理
Celery的架构由三部分组成,消息中间件(message broker),任务执行单元(worker)和任务执行结果存储(task result store)组成。
- Producer : 任务生产者. 调用 Celery API , 函数或者装饰器, 而产生任务并交给任务队列处理的都是任务生产者.(通过装饰器修饰调用producer,产生任务并加入到队列中)
- 消息中间件broker -将任务提交至任务队列
Celery本身不提供消息服务,但是可以方便的和第三方提供的消息中间件集成。包括,RabbitMQ, Redis等等
RabbitMQ和 Redis的区别:
https://blog.csdn.net/dd18709200301/article/details/79077839 - 任务执行单元worker- 负责将任务从任务队列中取出后的执行
Worker是Celery提供的任务执行的单元,worker并发的运行在分布式的系统节点中
!!注意:同一时刻,可以启用多个worker进行执行任务,只要启动worker,只要broker提交了任务,自动执行。 - 任务结果存储Task result store
Task result store用来存储Worker执行的任务的结果,Celery支持以不同方式存储任务的结果,包括AMQP, redis等
celery框架集成
常用框架 | 框架内celery依赖包 |
---|---|
Django | django-celery |
Pyramid | pyramid_celery |
Pylons | celery-pylons |
Flask | 不需要 |
web2py | web2py-celery |
Tornado | tornado-celery |
三、celery应用场景
异步任务:
将耗时操作任务提交给Celery去异步执行,比如发送短信/邮件、消息推送、音视频处理等等,提高系统的吞吐量和响应时间。
系统吞吐量是指在单位时间内中央处理器(CPU)从存储设备读取、处理、存储信息的量。
影响因素:
存储设备的存取速度,即从存储器读出数据或数据写入存储器所需时间;
CPU性能:时钟频率;每条指令所花的时钟周期数(即CPI);
指令条数;系统结构:如并行处理结构可增大吞吐量。
定时任务:
定时执行某件事情,比如每天数据统计
四、celery项目应用
-
定时任务:秒杀模块设计定时任务将信息保存到redis中
在秒杀课程的模块中,考虑到同一时间同时进行抢购,网站瞬时访问流量激增,所以采用了Redis分布式缓存系统,支持多种数据结构:秒杀系统最大的瓶颈一般都是数据库读写,由于数据库读写属于磁盘IO,性能很低,如果能够把部分数据或业务逻辑转移到内存缓存,效率会有极大地提升,设置定时任务,将参加活动的课程信息提前保存到redis中并设置过期时间,定时执行该任务即可。
-
异步任务:向会员推送生日祝福
异步任务:根据用户类型的不同,在会员生日的时候通过异步任务乡会员推送生日祝福信息,并向会员赠送平台优惠券,可用于课程的购买等
中间件选择的是rabbitmq,中间件常用的是redis和rabbitmq,选择rabbitmq的原因是:- Rabbitmq具有消息消费确认机制,如果发布一条消息,还没有消费者消费该队列,那么这条消息将一直存放在队列中,直到有消费者消费了该条消息,以此可以保证消息的可靠消费
- 实时性方面来对比redis实时性高,redis作为高效的缓存服务器,所有的数据都保存在内存中,所以它具有更高的实时性,我们向会员推送的生日祝福在生日当天推送即可,对实时性要求较低,rabbitmq完全可以胜任
- rabbitmq队列,每条消息都可以选择性持久化,持久化粒度更小,更灵活;redis是全部内容持久化;并且rabbitmq实现了后台监控平台,可以在该平台上看到所有创建的队列的详细情况,良好的后台管理平台可以方面我们更好的使用;而redis没有所谓的监控平台
相比较之下rabbitmq的优势就在于提供可靠的队列服务,并且可做到异步,而redis主要是用于缓存的,redis的发布订阅模块,可用于实现及时性,且可靠性低的功能。
五、celery项目问题及解决方案
1. beat启动时生成的pid文件需要手动删除
2. celery配置async包
错误原因:python3.6及其以上的版本已经将async收入关键字中,celery4.0版本也用到了async,如果不配置backend的话是不会出现这个错误的
解决方案:
- 先到 "Python\Python37\site-packages\kombu"目录下更改"async"文件夹名称,改成其他名称即可;
- 重启worker,修改代码 :将所有"async"改为,上一步新命的名;直至不再报
与"async"相关的错误.
3. ‘Command’ has no attribute ‘option_list’
解决方案:修改代码: 在 "Command"类下添加属性 option_list=()
classCommand(models.Model)):
option_list=() # 给这个类加个属性
pass
4. worker 可以正常启动,但是接不到任务
具体信息:celery AttributeError: ‘str’ objecthas no attribute ‘items’
错误原因:Redis 版本过高
解决方案:降低其版本
5. celery的定时任务会有一定时间的延迟。
我规定模拟登陆新浪微博任务每隔10个小时执行一次,那么定时任务第一次执行就会在开启定时任务之后的10个小时后才会执行。而我抓取微博需要马上执行,需要带上cookie,所以不能等那10个小时。这个没有一个比较好的解决方法,可以使用celery的crontab()来代替schdule斜体样式做定时,它会在启动的时候就执行。我采用的方法是第一次手动执行该任务,然后再通过schedule执行。