首先我本机测试时没有问题的,但是在线上docker中,任务一直显示 “Sending due task”。超时的任务是 django orm update 操作,本地不会出现这样的问题。

1. 是不是共用了redis db而不知情?

可能是别人也用这个 redis db 作为 broker,然后比人的任务很多并且排在了我的前面,而我又设置了超时时间

CELERYD_TASK_SOFT_TIME_LIMIT = 20

。于是我将 redis db 改为 61,重启后报错:

invalid DB index

  于是搜索 `redis max db number in centos`,在 Maximum number of DB in Redis 找到了答案。 redis 默认只有 16 个 db,但是不限制你设置 db 的数目大小,要记得 redis.conf 设置后要重启才能生效。同时,一个回答者认为 redis 不鼓励设置很多个 db。

(since Redis has a very small memory footprint when is has no data,
~1MB).

我不是运维,于是我将 BROKER 的 redis db 设置为 13。等待结果中。。。。。。(嗯!有这个 db。)

(PS:

我们是使用 docker 部署的,但是改变一个环境变量就需要重新 build 镜像,所以调试一次花的时间很长。我一般直接进入 docker 中,更改代码然后重启 supervisor,但是环境变量以及自定义的 supervisor 命令就没办法,只能重新 build 了。)

celery 队列

celery 有队列的功能,那么我是否能够定义一个自己的专有队列,然后让我的 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

我将 task_routes 改成 CELERY_ROUTES 就可以了。但是在 http://docs.celeryproject.org/en/latest/getting-started/first-steps-with-celery.html 中,就是写的 task_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.

我设置了一个自己的队列,然后 worker 只执行这个队列,但还是会出现 `SoftTimeLimitExceeded`。

多个 docker 重复执行 celery 任务

我使用 docker 部署,然后一次会创建三个容器,一个用来作为备份(只有确定版本稳定了才更新这个容器,否则这个容器一直不变),另外两个用于生产。我现在使用 celery 执行定时任务,在每个整点向微信服务器申请新的 access_token。到了整点,三个容器同时向微信服务器申请 token,然后就会暂时被微信服务器封掉 ip,因为请求的太频繁了。

之前我是使用 celery 加上 python timedelta(minutes=60),但发现每次重启容器的时候任务都会进行,于是就改成了在整点执行任务。

那我现在应该怎么处理呢?

我可以每次重启容器后,进入两个容器中,把 celery_worker 关闭,只留下一个容器执行 celery,可以是可以,但是手动操作太麻烦了。不知道你们是怎样解决这类问题的呢?

睡了一觉,早上想到:这个问题可以转变成:

两个除了启动时间不一样,其他如代码、环境变量等等都一样的程序,如何保证相同的 celery 任务不同时执行。我这里的任务还有一个隐藏条件:只要在一定时间范围内执行了就可以了,执行时间点不一定要扣的很死,比如一定在零点零分执行。

那我就把celery相同任务的执行时间错开。 我可以用随机数作为任务执行的分钟数,这个随机数是启动时生成的,于是任务就被错开了。然后每次任务执行时设置一个 redis key,然后任务执行前看看这个 redis key 是否不为空,避免重复执行。实践了一下是没有问题的,发生3个里面两个在同一份中的概率是,排列组合计算,忘了。

序列化 - Serializers

从 celery==3.1.23 升级到 celery==4.0.2,并删除 django-celery==3.1.17,因为 4.0+ 版本已经支持 Django 了。

遇到了序列化的问题,kombu.exceptions.EncodeError: <function get_file_info at 0x1115c7bf8> is not JSON serializable

 函数不能序列化为 json,我就很纳闷,为什么 celery==3.1.23 就可以呢?为了确认是这个问题,我还重新安装 celery==3.1.23,然后就不会报错。我直接搜索 `kombu.exceptions.EncodeError not JSON serializable` 没有找到答案,搜索 `celery not JSON serializable` 也没有找到答案。没办法的情况下,只能更改 celery tasks 定义了。将之前使用函数作为参数的任务改一下。但是,最后遇到问题,有 Django 的 queryset 作为任务,那这样还要将对应querset的参数传入 celery task,我感觉做不了了。于是问同事,刚开始他也没思路,后来我强调 celery==3.1.23 可以序列化而 celery==4.0.2 会报错,他突然想起,说:“celery==4.0.2 默认使用 JSON 作为 serializer ,而 celery==3.1.23 默认使用 pickle”。经过搜索后,将 serializer 改为 pickle,在 celeryconfig.py 中增加如下配置:

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

然后就可以了。

还有celery依赖包的问题,比如 kombu 之类的,不能放进 requirements.txt 中如果你不是单独需要的话。因为,当更换 celery 版本的时候,还要手动更换 kombu 这些celery依赖包的版本。所以,在 pip freeze 后也需要做出选择,不把包的依赖包放进去。

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

  • 升级celery前没有评估好各个引用方法能否改写,之前也确实没有想到会遇到这样的问题;
  • 搜索技巧的问题。直接按照报错信息“kombu.exceptions.EncodeError: <function get_file_info at 0x1115c7bf8> is not JSON serializable”去搜索,没有找到答案。如果改用 "differences between celery3 and celery serializers",我就能发现这个:http://docs.celeryproject.org/en/latest/whatsnew-4.0.html,然后页面内搜索 `serializer`,就能发现有一个标题写的很清楚“Json is now the default serializer
  • 问人要提早问,不要不好意思。之前是问的太多了,现在是问的太少了。有些问题可能要花很多时间去找答案,但他人可能了解相关的知识,只要你提问足够具体。
  • 升级之前没有了解新的变化。我想的是不用依赖 django-celery 以及版本更高的话文档会更及时。

能否动态增加 celery 任务?如何给定时任务增加参数?

celery 是命令行启动的,那么能否在启动后动态增加呢? 参考:http://stackoverflow.com/questions/11449661/how-to-pragmatically-schedule-celery-task-with-dynamic-inputs。一种是通过函数,函数能够接受参数或者生成参数;而是celery中可以配置定时任务的参数,那如果有很多,就要生成这些代码?celery配置不能使用循环?

“定时任务增加参数”,是否与在一个任务中做完所有参数的工作相同?

附:

celery 序列化器的不同?为什么要将 JSON 作为默认序列化器?

我使用celery以及docker部署遇到的问题的更多相关文章

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

    问题1 - Sending due task 本机测试时没有问题的,但是在线上 docker 中,任务一直显示 "Sending due task".超时的任务是 Django O ...

  2. ASP.NET Core开发-Docker部署运行

    ASP.NET Core开发Docker部署,.NET Core支持Docker 部署运行.我们将ASP.NET Core 部署在Docker 上运行. 大家可能都见识过Docker ,今天我们就详细 ...

  3. Docker部署Hadoop集群

    Docker部署Hadoop集群 2016-09-27 杜亦舒 前几天写了文章"Hadoop 集群搭建"之后,一个朋友留言说希望介绍下如何使用Docker部署,这个建议很好,Doc ...

  4. 程序开发使用docker部署

    我们公司自己研发了一套 grand-line 系统,使用 docker 来部署项目. 我是第一批小白鼠,一开始网络差,build 一次要半个小时,连接进入 web shell 也很慢,部署一个微信项目 ...

  5. Docker部署SDN环境

    2014-12-03 by muzi Docker image = Java class Docker container = Java object 前言 5月份的时候,当我还是一个大学生的时候,有 ...

  6. 在生产环境使用Docker部署应用

    导读 Docker现在越来越流行,但是真正在生产环境部署Docker还是个比较新的概念,还没有一个标准的流程.作者是ROR的程序员,作者结合平时的部署经验,联系Docker的特点,向大家分享了其在生产 ...

  7. Docker 使用指南 (六)—— 使用 Docker 部署 Django 容器栈

    版权声明:本文由田飞雨原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/98 来源:腾云阁 https://www.qclou ...

  8. NET Core Docker部署

    NET Core Docker部署 前言 在前面文章中,介绍了 ASP.NET Core在 macOS,Linux 上基于Nginx和Jexus的发布和部署,本篇文章主要是如何在Docker容器中运行 ...

  9. Docker部署Elasticsearch集群

    http://blog.sina.com.cn/s/blog_8ea8e9d50102wwik.html Docker部署Elasticsearch集群 参考文档: https://hub.docke ...

随机推荐

  1. 心理控制方法——阅读Notes

    1.自助式情感手术 祛除自我意象中的伤疤的要点 2. 你制造错误,但是错误不应造就你    你身上的缺点不是你的错  3. 不仅要原谅别人,也要原谅自己 4. 怨恨是一条通向失败的道路 5. 注意来 ...

  2. 关于tableview内cell自定义的注册以及创建

    自定义cell的方法主要有两种,storyboard以及xib(假设新建的是cellTableViewCell类) 比较倾向于xib方式使用xib在xib文件内将自定义的cell绘制好后导入到调用文件 ...

  3. github代码上传之命令提交

    Git GUI的用法比较简单,随便弄弄就可以将本地git库中的代码提交到远端github服务器,所以想把Git bash这玩意儿的操作流程快速过一遍,主要是做个笔记,以后忘记了可以看看怎么操作的. 首 ...

  4. jenkins打包成功,部署失败

    环境一直正常,更新了tomcat版本后自动部署报错 ERROR: Publisher hudson.plugins.deploy.DeployPublisher aborted due to exce ...

  5. hadoop2.4.1集群搭建

    准备Linux环境 修改主机名: $ vim /etc/sysconfig/network NETWORKING=yes HOSTNAME=hadoop001 修改IP: # vim /etc/sys ...

  6. 【JSP】JSP基础学习记录(一)—— 基础介绍以及3个编译指令

    序: 从实现到现在一直是以.net为主,但偶尔也会参与一些其他语言的项目.最近需要对一个Java Web项目进行二次开发,一直没学习过JSP所以买了几本书自学试试.参考资料为<轻量级Java E ...

  7. coursera机器学习笔记-多元线性回归,normal equation

    #对coursera上Andrew Ng老师开的机器学习课程的笔记和心得: #注:此笔记是我自己认为本节课里比较重要.难理解或容易忘记的内容并做了些补充,并非是课堂详细笔记和要点: #标记为<补 ...

  8. Linux简介及常用命令使用2--linux常用命令:查看 删除 编辑 创建等

    cd .       // 进入当前目录 cd ~     //进入根目录 pwd      //当前路径 echo "my name is makaidong">makai ...

  9. ixgbe 82599 固定源与目标, UDP, 64字节小包, 1488w pps 单核CPU软中断sirq 100%

    ixgbe 82599 固定源与目标, UDP, 64字节小包, 1488w pps 单核CPU软中断sirq 100% 注: 测试使用, 正常应用不要开启 五元组不同, 开启ntupleethtoo ...

  10. 浅谈C++设计模式之单例模式

    单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 通常我们可以让一个全局变量使得一个对象被访问,但它不能防止客户实例化多个对象,一个最好的办法就是让类自身负责保护它的唯一实例,这个类可 ...