首先我本机测试时没有问题的,但是在线上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. C#复习⑦

    C#复习⑦ 2016年6月22日 11:50 Main Exception & Namespaces & Assemblies 异常 & 命名空间 & 程序集 1.tr ...

  2. SVN安装使用小结

    SVN在实际的项目开发中有很广泛的用途.一开始接触SVN(Subversion),思路并不清楚,现在总算理清了. 声明:本文并不是系统地对SVN做介绍,而是笔者的使用总结,个人认为的一些要点,可能对初 ...

  3. Entity Framework在Asp.net MVC中的实现One Context Per Request(附源码)

    上篇中"Entity Framework中的Identity map和Unit of Work模式", 由于EF中的Identity map和Unit of Work模式,EF体现 ...

  4. 驳 GarbageMan 的《一个超复杂的简介递归》——对延迟计算的实验和思考

    这是一篇因骂战而起的博文,GarbageMan 在该文章回复中不仅对我进行了侮辱,还涉及了我的母校,特写此文用理性的分析和实验予以回击. 在此也劝告 GarbageMan,没什么本事就别在那叫嚣了,还 ...

  5. AS与.net的交互——详解UrlRequest

    在.net中我们知道有一个叫做WebHttpRequest的东西,用它我们可以实现各种网络偷窥,监控,采集和机器人,如果外加一 个模式识别,那真是吊爆了... 在as中我们也可以实现同样的功能,而且我 ...

  6. maven 安装alipay-sdk包到本地及远程仓库

    安装到本地:mvn install:install-file -DgroupId=com.alipay -DartifactId=sdk-Java -Dversion=*** -Dpackaging= ...

  7. Linux 性能优化工具 perf top

    1. perf perf 是一个调查 Linux 中各种性能问题的有力工具. NAME perf - Performance analysis tools for Linux SYNOPSIS per ...

  8. Java api 入门教程 之 JAVA的IO处理

    IO是输入和输出的简称,在实际的使用时,输入和输出是有方向的.就像现实中两个人之间借钱一样,例如A借钱给B,相对于A来说是借出,而相对于B来说则是借入.所以在程序中提到输入和输出时,也需要区分清楚是相 ...

  9. Toritoisegit记住用户名密码

    TortoiseGit每次连接git都得输入密码了,如果我们用到的比较频繁这样是很麻烦的,那么下面我们来看一篇关于window设置TortoiseGit连接git不用每次输入用户名和密码的配置,具体的 ...

  10. Altium Desiner 警告 adding hidden net

    这是因为 一些元件 隐藏了 vcc GND 或者没有使用vcc GND ,用不着它也报警告了. 这里可以将 vcc GND删掉这个管脚.