我使用 Docker 部署 Celery 遇到的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我使用 Docker 部署 Celery 遇到的问题相关的知识,希望对你有一定的参考价值。

问题1 - Sending due task

本机测试时没有问题的,但是在线上 docker 中,任务一直显示 “Sending due task”。超时的任务是 Django ORM update 操作。

猜测 - 是否与其他 Celery 公用了 redis db?

其他 Celery 也使用了这个 redis db 作为 broker,有很多其他 Celery 的任务在队列中,轮不到我的任务。于是我将 redis db 设置为 13,但没有修复这个问题。

使用队列

那么我是否能够定义一个自己的专有队列,然后让我的 worker 执行自定义队列中的任务呢?这样就不需要挑别人未使用的 redis db 了。
根据 http://docs.celeryproject.org/en/latest/userguide/routing.html#basics 以及 http://docs.celeryproject.org/en/latest/getting-started/first-steps-with-celery.html 我将我的任务放在队列中,然后报错

ImproperlyConfigured:

Cannot mix new setting names with old setting names, please
rename the following settings to use the old format:

task_routes -> CELERY_ROUTES

这是因为 Celery 有两种命名规范。

New lowercase settings
Version 4.0 introduced new lower case settings and setting organization.

The major difference between previous versions, apart from the lower case names, are the renaming of some prefixes, like celerybeat_ to beat_, celeryd_ to worker_, and most of the top level celery_ settings have been moved into a new task_ prefix.

Celery will still be able to read old configuration files, so there’s no rush in moving to the new settings format. - From http://docs.celeryproject.org/en/latest/userguide/configuration.html#example-configuration-file

在设置队列后,还是没有解决这个问题。

问题2 - 多个 docker 重复执行 Celery 任务

使用 docker 部署一次会创建三个容器,一个用作备份,两外两个用于生产。现在 Celery 会每小时向微信服务器申请 access token,然后就会被微信服务器封掉 ip,因为请求太频繁了。

由于只要在本地的 access token 过期前申请新的 access token 就可以,所以不一定要在整点执行。于是我将申请 access token 的定时任务设置为随机分钟数,然后执行前检查 redis,如果其他 docker 中的 Celery 已经执行过来,则不再执行。

问题3 - Not JSON serializable

错误信息:

kombu.exceptions.EncodeError: <function get_file_info at 0x1115c7bf8> is not JSON serializable

这是从 celery==3.1.23 升级成 celery==4.0.2 之后发生的,在我重新安装 celery==3.1.23 后就不会报错。我搜索 kombu.exceptions.EncodeError not JSON serializablecelery not JSON serializable 都没有找到答案。
没办法之后,就问同事,刚开始他也没思路,后来我强调 celery==3.1.23 可以序列化而 celery==4.0.2 会报错,他突然想起:“celery==4.0.2 默认使用 JSON 作为 serializer ,而 celery==3.1.23 默认使用 pickle。”。然后搜索 Add Celery serializer,在 celeryconfig.py 中增加如下配置:

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

Celery 依赖问题

Celery 的依赖包不应该放进 requirements.txt 里面。因为当更换 Celery 版本的时候会导致依赖出问题。所以,不要将包的依赖放进 requirements.txt 中。

反思一下,存在以下问题:

  • 升级之前没有思考到库的变化对代码的影响,尤其是不兼容的版本版本升级(有 3.1.23 到 4.0.2)。
  • 问人要提早问,不要不好意思。之前是问的太多了,现在是问的太少了。有些问题可能要花很多时间去找答案,但他人可能了解相关的知识,只要你提问足够具体。

以上是关于我使用 Docker 部署 Celery 遇到的问题的主要内容,如果未能解决你的问题,请参考以下文章

docker下的celery

是否有人将 django celery worker 实现为 docker 容器,它仅在分配任务时运行

Docker,Celery,组合方法失败

docker-compose 和优雅的 Celery 关闭

使用celery遇到的坑

Docker + Celery 告诉我不要以 root 身份运行,但一旦我不这样做,我就没有运行权限