Celery 3.x 升级至 celery 4.x(转)

摘要:
预准备首先介绍下项目中celery相关的依赖包,目前项目中主要使用的是celery进行异步处理,使用celery-redbeat设置定时异步任务,使用flower进行异步任务的监控。升级前相关包的版本情况如下:celery==3.1.25celery-redbeat==0.10.4flower==0.9.1升级过程在升级之前,对相关情况进行了调研,发现celery和celery-redbeat关系紧密,只升级单个容易出现无法启动的问题,于是将celery和celery-redbeat一起升级,flower在下一步再进行升级。

预准备

首先介绍下项目中 celery 相关的依赖包,目前项目中主要使用的是 celery 进行异步处理,使用 celery-redbeat 设置定时异步任务,使用 flower 进行异步任务的监控。升级前相关包的版本情况如下:

celery==3.1.25
celery-redbeat==0.10.4
flower==0.9.1

升级过程

在升级之前,对相关情况进行了调研,发现 celery 和 celery-redbeat 关系紧密,只升级单个容易出现无法启动的问题,于是将 celery 和 celery-redbeat 一起升级,flower 在下一步再进行升级。具体过程如下:

celery 官方升级教程

升级第一步,首先去了解了官方给出的升级教程,官方给出的升级步骤主要分为四步:

  1. 将 celery 版本升级为 3.1.25,在这个版本中增加了对新的消息协议的正向兼容性, 因此之后可以直接从3.1.25 升级至 4.0,由于原本项目中的 celery 已经处于这个版本,此步骤可省略;

  2. 升级配置,使用新的设置名,官方为了保证配置名的一致性,将 celery 的配置进行了更改,但是此次更改是向后兼容的,也就是老的配置名还可以用,但是将来会废弃。完整的对应关系可以见官方链接

  3. 阅读官方给出的重要提示,主要是此次版本升级的一些重要变化,如下所示:

    • 不再支持 Python 2.6 ;

    • 这是最后一个支持 Python 2 的主要版本了,从 celery 5.0 开始只支持 Python 3.5+ ;

    • celery 4.x 只支持 Django 1.8 或以上;

    • 不再支持 Windows 和 Jython ;

    • 移除一些原来的功能,包括celery.task.http,app.mail_admins,celery.contrib.batches

    • 由于缺乏支持移除一些功能,不再支持使用Django ORM,SQLAlchemy,CouchDB,IronMQ,Beanstalk作为 broker ;

    • 完全移除一些功能,包括--autoreload, 实验性的线程池功能,force_execv, 使用amqp作为结果存储的功能被废弃;

    • 使用了新的任务消息协议,新的消息协议是默认开启的,而且不是向后兼容的,但是 3.1.25 版本增加了对新协议的兼容性,因此建议先升级 3.1.25 再升级 4.0 ;

    • 小写的配置名,老的配置依旧可用,但是建议升级为新的配置,官方提供了下面的命令帮助自动升级配置;

      celery upgrade settings proj/settings.py
      
    • 目前是默认的序列化采用 json,如果项目中依赖 pickle 进行序列化,可以使用下面的命令指定 :

      task_serializer = 'pickle'
      result_serializer = 'pickle'
      accept_content = {'pickle'}
      
    • Task 基类不再自动注册任务了,任务类不再使用特殊的元类自动注册任务了,现在是使用app.task装饰器进行注册。

      如果使用基类任务,需要手工注册任务,代码如下所示:

      class CustomTask(Task):
          def run(self):
              print('running')
      CustomTask = app.register_task(CustomTask())
      

      最佳实践是使用自定义的任务类复写一般的行为,然后使用任务装饰器实现任务,代码如下:

      @app.task(bind=True, base=CustomTask)
      def custom(self):
          print('running')
      
    • 任务参数会在调用时进行校验, 如果不一致会报错,但是也支持关闭检查;

    • Redis 事件不是向后兼容的,目前fanout_patternsfanout_prefix传输选项是默认开启的。

      没有启动这些标志的 Worker / 监视器是不能看到禁用此标志的 Worker 的。他们依然可以执行任务,单不能彼此接收监视消息。

      为了保持向后的兼容性,你可以在 3.1 的版本中先开启这些标志,然后再升级至 4.0,配置如下:

      BROKER_TRANSPORT_OPTIONS = {
          'fanout_patterns': True,
          'fanout_prefix': True,
      }
      
    • Redis 的优先级颠倒了,目前优先级0是最低的,优先级9是最高的,这是为了与AMQP保持一致;

    • Auto-discover目前支持 Django app 配置

    • Worker 直接队列不再使用自动删除(auto-delete)

    • 老的命令行程序被移除,安装 celery 不再安装 celeryd, celerybeat 和 celeryd-multi 程序,可以使用新的命令,替代情况如下:

      老命令新命令
      celerydcelery worker
      celerybeatcelery beat
      celeryd-multicelery multi
  4. 升级至 celery 4.0;

按照上面的流程将 celery 的版本升级至celery 4.2

celery-redbeat 配置更新

celery-redbeat 对于 celery 3.x 和 celery 4.x 使用的是不同的配置名,需要根据需要进行更新,pypi 上有相关的介绍,具体如下所示:

  1. celery-redbeat 基本配置名针对 celery 3.x 和 celery 4.x 有所不同,对应关系如下:

    celery 4.xcelery 3.x
    redbeat_redis_urlREDBEAT_REDIS_URL
    redbeat_key_prefixREDBEAT_KEY_PREFIX
    redbeat_lock_keyREDBEAT_LOCK_KEY
    redbeat_lock_timeoutREDBEAT_LOCK_TIMEOUT
  2. celery-redbeat 定义具体定时任务列表,在 celery 3.x 中使用的是变量的CELERYBEAT_SCHEDULE,但是在 celery 4.x 中使用的是变量beat_schedule, 也需要对应更新

在更新了celery-redbeat 的配置之后,将 celery-redbeat 的版本也更新至最新版celery-rebeat 0.12.0

异常处理 celery 配置生效异常

由于项目中依赖 pickle 进行序列化,因此在前面的步骤中使用新的配置指定使用 pickle 进行序列化,但是在实际启动中发现,依旧报错 datetime 格式序列化出错。在实际测试中发现,在配置文件中加上老的配置参数就能正常序列化了,即加上:

CELERY_TASK_SERIALIZER = 'pickle'
CELERY_RESULT_SERIALIZER = 'pickle'
CELERY_ACCEPT_CONTENT = ['pickle']

没有确定是不是 celery 的配置读取还有坑,但是多增加老的配置对运行不会影响 celery 的执行,因此暂时没有深入研究具体原因

异常处理'NoneType' object has no attribute 'hostname'

升级之后重启 celery 时,出现了异常提醒 ` ‘NoneType’ object has no attribute ‘hostname’` ,

查找定位后发现有人在提出过类似的问题, 现象出现在kombu==4.2.1升级至kombu==4.2.2之后,kombu 是 celery 包的间接依赖,升级时没有指定版本,确认了本地的 kombu 的版本,确实在升级之后 celery 自动安装的是kombu==4.2.2

看起来应该是 kombu 新版本引入的bug,于是解决方案就比较明确了,将kombu==4.2.1写入requirements.txt,降级回去之后问题得到解决

异常处理RuntimeError('no suitable implementation for this system')

在本地测试正常执行后,在 docker 环境下使用 gunicorn 启动 web 服务,并使用 eventlet 进行协程并行化,出现了上面的异常RuntimeError('no suitable implementation for this system')

依旧是一番搜索后发现,有人提出过类似的问题,在 eventlet 上 github 上,也有人提出这个issue, 看起来直到目前为止,这个问题依旧没有得到解决。看到大部分给出的意见,这个 bug 应该是 eventlet 引入的。

最终我们抛弃了 eventlet , 投奔了 gevent , 一方面是因为这个 bug,另外一方面也是因为 gevent 使用者更多,更新更加及时,而 eventlet 看起来越来越缺乏维护了,从 eventlet 切换为 gevent 之后问题得到解决

对于希望继续使用 eventlet 的开发者而言,可以将 eventlet 的版本固定在 0.19.0 , 即指定eventlet==0.19.0

待解决

在解决了上面的问题中,在本地和测试环境发现的问题就已经都解决了,信心满满地上线,发现依旧依旧出现了下面的两个问题,目前暂时没有解决,因此临时将版本回滚,后续解决问题再上线,到时候再更新此文章

异常待处理'list' object has no attribute 'decode'

这个 bug 在 celery 的 github 上已经有人报过这个bug, 看起来是新版本的 celery 在使用 redis 作为 backend 时还存在一些问题,官方也没有正面回应这个问题,估计需要后续版本在看能否修复

异常待处理 异步任务没有正常执行

在实际执行后,发现异步任务没有正常执行起来,不确定是否是因为'list' object has no attribute 'decode'的异常,这个问题需要后续进行进一步定位

参考:https://hustyichi.github.io/2019/03/26/celery-upgrade/

免责声明:文章转载自《Celery 3.x 升级至 celery 4.x(转)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Cookie工具类(获取cookie,设置cookie)python利用递归去遍历多重dict下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Celery学习--- Celery在项目中的使用

可以把celery配置成一个应用,注意连接文件命名必须为celery.py 目录格式如下 项目前提: 安装并启动Redis CeleryPro/celery.py   【命名必须为celery.py】 # 将相对路径转换为绝对路径 from __future__ import absolute_import, unicode_literals...

分布式任务队列--Celery的学习笔记

一、Celery简介   Celery是一个简单,灵活,可靠的分布式系统,用于处理大量消息,同时为操作提供维护此类系统所需的工具。它是一个任务队列,专注于实时处理,同时还支持任务调度。   所谓任务队列,是一个逻辑上的概念,可以将抽象中的任务发送到指定的执行任务的组件,任务队列可以跨线程或机器运行。   Celery是基于Python开发的分布式异步消息任...

使用 supervisor 管理 Celery 服务

使用 supervisor 管理 Celery 服务 Celery 后台运行 如果我们想让celery worker运行在后台而不是终端上,在后台以守护进程的方式运行,我们可以使用supervisor进行管理。 celery 的安装 pip install celery celery的安装很简单,直接通过pip就能够安装,并且本身没有任何的配置,如果需要命...

Django的celery配置(包括定时任务、队列)

一、安装celery Django项目不需要安装celery这个包,可以直接使用django-celery这个包,,先来安装它,在终端中输入: pip install django-celery 二、安装rabbitmq,建立celery队列 我做的项目用的就是rabbitmq,按道理来说,也是可以用redis作为消息队列的,但是rabbitmq更好,此...

Pycharm下 debug Celery

Outline 项目是 Flask + Celery 实现异步,需要断点调试 celery task 中的代码,但celery是通过命令行启动的,怎么借助pycharm进行断点调试? Pycharm断点调试Flask,参见:https://www.cnblogs.com/bigtreei/p/14742015.html  Pycharm断点调试Scrapy...

Flask- celery (芹菜)

一.什么是Celery?   中文名翻译为芹菜,是flask中处理异步定时周期任务的第三方组件 二.基本结构  1.需要跑的任务代码app   2.用管道broker与用于存储任务(就是个缓存)  工具一般用redis  或者用rabbitMQ(兔子)   3.执行任务的人worker  简单实例 首先建立三个文件分别写入一下代码 from celery...