首先我本机测试时没有问题的,但是在线上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. Linux Shell 网络层监控脚本(监控包括:连接数、句柄数及根据监控反馈结果分析)

    脚本监控: 获取最大句柄数的进程: 链接分析: 脚本片段: case "$handle" in 2) echo "The handle of the process : ...

  2. get和post的区别与乱码问题解决

    ★ get和post的区别:     1.get请求通过url地址发送请求参数,可以在地址栏上直接显示     2.post请求通过请求体发送请求参数,不会再地址栏上显示     3.get在地址栏显 ...

  3. Sql Server之旅——第十一站 简单说说sqlserver的执行计划

    我们知道sql在底层的执行给我们上层人员开了一个窗口,那就是执行计划,有了执行计划之后,我们就清楚了那些烂sql是怎么执行的,这样 就可以方便的找到sql的缺陷和优化点. 一:执行计划生成过程 说到执 ...

  4. js日期比较

    alert(EDate< new Date().format("yyyy-MM-dd hh:mm:ss")); Date.prototype.format = functio ...

  5. HTTP 请求报文 响应报文

    引言 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议.所有的WWW文件都必须遵守这个标准.设计HTTP最初的目的是为了提供一种发 ...

  6. 浅谈C++设计模式之工厂方法(Factory Method)

    为什么要用设计模式?根本原因是为了代码复用,增加可维护性. 面向对象设计坚持的原则:开闭原则(Open Closed Principle,OCP).里氏代换原则(Liskov Substitution ...

  7. 在报表中给session赋值实现报表间参数共享

    1. 问题描述 在报表开发工具FineReport中,若有几张不同的报表,每张报表都有一个共同的项可以选择,比如日期时间.我们希望选择了第一张报表的时间之后,其他报表的默认时间都变为第一张报表选择的时 ...

  8. Windows Azure Storage图形界面管理工具

    上一篇我们介绍了用PowerShell将Windows Azure的存储服务当网盘来使用.如果感觉还不够简单,那么这次我们来看看还有哪些使用起来更方便的图形界面管理工具吧.当然,这些工具必要支持中国版 ...

  9. position:absolute/relative/fixed小结

    1.绝对定位:position:absolute; 当一个div块的位置被定义为绝对定位absolute时,也就意味着它失去了文档流的位置,后面的文档流会紧跟着补上来接替它的位置.如果上下左右的绝对偏 ...

  10. 广州APP开发外包公司哪家比较好?广州达到信息技术有限公司技术到底怎么样?

        广州APP开发公司哪家比较好,广州手机APP软件开发公司广州达到信息表示:用户的刚性需求是公司使用手机APP软件盈利的根本前提和基础,所以开发一款手机APP应用时必须从客户的角度来思考.因此公 ...