Celery 4.0 系列latentcall变更全解析安全加固、任务注册新 API 与关键修复【免费下载链接】celeryDistributed Task Queue (development branch)项目地址: https://gitcode.com/gh_mirrors/ce/celery本文以官方仓库 docs/history/changelog-4.0.rst 为核心骨架系统梳理 Celery 4.0.x 系列代号 latentcall从 4.0.0rc7 到 4.0.2 的版本演进包括影响所有用户的CELERYSA-0003默认反序列化安全公告、类式任务注册新 APIapp.register_task、chain()语义统一以及 worker、结果后端、画布canvas等模块的数十项关键修复。读完本文你将理解 4.0 版本的安全基线配置方式、新 API 的正确用法以及从 3.1 升级到 4.0 时必须处理的破坏性变更清单。4.0.x 版本时间线概览Celery 4.0 是 2016 年发布的大版本系列与 3.1 相比在底层依赖Kombu 4.0、任务执行模型、结果后端等方面均有重大变化。4.0.x 系列的三个 bugfix 版本发布时间如下版本发布日期定位4.0.0rc72016-11-02 01:30 P.M PDT发布候选包含两处重要变更说明4.0.02016-11-04 02:00 P.M PDT正式版本4.0.12016-12-08 05:22 PM PST安全修复 一批任务/Worker 修复4.0.22016-12-15 03:40 PM PST依赖升级 JSON 序列化等修复其中 4.0.0 的完整新特性概览见仓库中的 docs/history/whatsnew-4.0.rst而本文聚焦于 4.0.x 系列各 bugfix 版本的变更细节。CELERYSA-0003默认反序列化配置不安全4.0.1 安全修复4.0.1 版本最重要的变更是修复了一个安全问题CELERYSA-0003Insecure default configuration完整公告见仓库 docs/sec/CELERYSA-0003.txt。问题背景Celery 4.0.0 的默认accept_content配置允许反序列化 pickle 消息即使应用被配置为以 JSON 格式发送消息。具体而言4.0.0 的默认配置等价于app.conf.accept_content [json, pickle, msgpack, yaml]这意味着 worker 会接受并反序列化上述四种序列化格式的消息。风险等级被评估为low原因是攻击者需要先获得消息代理broker的访问权才能向 Celery worker 发送恶意消息——但这依然是一个明显的纵深防御缺口如果攻击者能向 broker 投递 pickle 载荷反序列化过程可能触发任意代码执行。修复方案4.0.1 修复了不安全默认值将默认accept_content收紧为只接受 JSON。这一默认值在当前仓库源码中可以直接验证celery/app/defaults.py 中定义了DEFAULT_ACCEPT_CONTENT (json,)并在 celery/app/defaults.py 的配置命名空间中注册为accept_content选项类型为 list。也就是说从 4.0.1 起未显式配置accept_content的应用默认只接受 JSON 序列化的消息pickle 等格式默认被拒绝。如果你仍停留在 4.0.0也可以显式配置以收紧安全性app.conf.accept_content [json]或者直接升级$ pip install -U celery安全基线建议即使在新版本中除非确有需要如与旧版 worker 互通都不应把pickle、yaml重新加入accept_content。如需自定义请显式列出最小需要的序列化格式集合。类式任务注册新 APIapp.register_task4.0.14.0.1 为类式class-based任务引入了新的注册方式调用app.register_task而非旧式写法Issue #3615。示例from celery import Celery, Task app Celery() class CustomTask(Task): def run(self): return hello app.register_task(CustomTask())当前源码中的实现位于 celery/app/base.py关键逻辑如下def register_task(self, task, **options): Utility for registering a task-based class. task inspect.isclass(task) and task() or task if not task.name: task_cls type(task) task.name self.gen_task_name( task_cls.__name__, task_cls.__module__) existing self.tasks.get(task.name) if existing is not None and existing is not task: self._warn_duplicate_task_name(...)从源码可以推断出几点实现细节既接受类也接受实例register_task会通过inspect.isclass(task)判断传入的是类还是实例如果是类会自动实例化自动生成任务名如果任务没有显式指定name会通过gen_task_name基于类名和模块名自动生成对应 4.0.1 中确保类式任务在注册前拥有名称的修复Issue #3616重名告警注册时若发现同名任务已存在会通过_warn_duplicate_task_name发出警告。注意源码注释特别说明这个 API 主要是为了兼容旧式Celery 1.0 风格的任务类新项目应优先使用app.task装饰器。4.0.1 中与任务注册相关的其他修复还包括参数检查支持 Python 3 的 keyword-only 参数Issue #3658由 sww 贡献task-sent事件即使配置开启也可能未发送Issue #3646修复 Python 3 下任务接收*args时的类型检查崩溃该问题在 4.0.2 中继续修复Issue #3678registry_cls参数此前不再生效Issue #3613本版本恢复其作用。GroupResult.restore新增app参数4.0.24.0.2 为GroupResult.restore增加了app参数Issue #3669由 Andreas Pelme 贡献使其与GroupResult构造函数的调用方式保持一致。当前实现位于 celery/result.pyclassmethod def restore(cls, id, backendNone, appNone): Restore previously saved group result. app app or ( cls.app if not isinstance(cls.app, property) else current_app ) backend backend or app.backend return backend.restore_group(id)这个改动意味着当你在多个 Celery 应用共存的环境中恢复组结果时可以显式指定所属的app从而让结果后端的解析更准确from celery.result import GroupResult result GroupResult.restore(group_id, appmy_app)安全地表示不可序列化对象saferepr系列修复4.0.1 与 4.0.2 针对saferepr用于安全地生成对象 repr避免在日志/报错中触发递归或编码异常的工具做了多项修复4.0.1saferepr尝试将可迭代对象展示为 list、将映射展示为 dict更可读修复 Python 3 下格式化bytes时的 unicode 错误Issue #3610正确表示含非 ASCII 字符的字节串Issue #36004.0.2修复 Python 2 下 bytestring 中 unicode 的处理Issue #3676。这些修复直接影响 worker 日志与异常信息中对任务参数等对象的展示可靠性尤其是在参数包含二进制或非 ASCII 数据时。Redis 结果后端新增redis_socket_connect_timeout4.0.14.0.1 为 Redis 结果后端新增了redis_socket_connect_timeout配置项同时修复了一个此前将socket_connect_timeout参数错误地传给 UNIX socket 连接、导致崩溃的问题。当前源码在 celery/backends/redis.py 中的读取逻辑如下socket_timeout _get(redis_socket_timeout) socket_connect_timeout _get(redis_socket_connect_timeout) retry_on_timeout _get(redis_retry_on_timeout) socket_keepalive _get(redis_socket_keepalive) health_check_interval _get(redis_backend_health_check_interval)配置示例app.conf.redis_socket_connect_timeout 5 # 连接超时秒此外4.0.1 还修复了 Redis/memcache 后端使用result_expires来设置 chord 计数器过期时间的问题Issue #3573由 Tayfun Sen 贡献。result_expires的默认值为 1 天timedelta(days1)定义于 celery/app/defaults.pychord 计数器的生命周期从此与普通结果保持一致。Worker 行为修复与-O参数问题4.0.x 系列修复了多个直接影响 worker 稳定性的缺陷硬时间限制失效Issue #36184.0.1硬时间限制hard time limit此前不再被尊重本版本恢复软时间限制日志显示错误4.0.1soft time limit 日志原本显示Trues而非具体的秒数本版本修正inspect stats的KeyErrorIssue #36214.0.1当-Ooptimization参数被设置为fast、fair之外的任意值时inspect stats会抛出KeyError本版本修复重试任务不再回到原始队列Issue #36224.0.1任务重试retry时本应重新投递但此前不会发送到原始队列本版本修复eventlet/gevent 池的 AMQP 心跳支持Issue #36494.0.1修复了异步池下的心跳问题事件生产者改用connection_for_WriteIssue #35254.0.1事件发送统一走写连接避免读写连接混淆Python 3 下apps/worker.py中 None/int 类型比较崩溃Issue #36314.0.1Python 3.x 下 worker 启动横幅缺少 logoIssue #36274.0.1由 Brian Luan 贡献。画布Canvas与任务执行修复chord 单任务头部的ValueErrorIssue #36084.0.1由 Viktor Holmqvist 贡献当 chord 的 header 只有一个任务时会抛出ValueError本版本修复group的 JSON 序列化错误Issue #36884.0.2修复了keys must be string报错——group对象此前在 JSON 序列化时失败inspect active等命令的 JSON 序列化问题Issue #36674.0.2信号signals中的 saferef 错误Issue #36704.0.2修复使用信号时的saferef异常Python 2.7.5 及更早版本pack需要 bytes 参数Issue #36744.0.2修复 prefork 池在旧版 Python 2.7 下的崩溃。Beat 与数据库结果后端shelve 中的字符串问题Issue #36444.0.1由 Alli 贡献修复 Beat 使用 shelve 持久化调度信息时的字符串处理错误Django 设置升级命令修复Issue #35634.0.1由 François Voron 贡献Elasticsearch 结果后端_index方法缺少 body 参数Issue #36064.0.1由何翔宇贡献依赖修复4.0.1 修复了celery[redis]捆绑安装问题Issue #3643由 Rémi Marenco 贡献celery[sqs]捆绑包现在额外要求pycurlIssue #3619。4.0.0rc7 的两处重要破坏性变更4.0.0rc7 包含两处需要升级用户特别注意的变更1. 数据库结果后端设置名重命名sqlalchemy_*→database_*从 4.0.0rc7 起数据库结果后端database result backend相关的设置名从sqlalchemy_*全部改为database_*。官方明确表示sqlalchemy_命名的设置在 4.0 中完全不会生效因此升级前必须重命名且官方不会提供别名因为 3.1 中并不支持这些设置没有兼容包袱。对应地仓库中的数据库后端实现位于 celery/backends/database/包含__init__.py、models.py与session.py三个模块。2.chain(A, B, C)与A | B | C语义统一chain(A, B, C)现在与A | B | C的行为完全一致。这意味着调用chain()返回的不一定是一个链chain对象——根据工作流能否被优化它可能返回 group 或其他类型。也就是说chain()不再保证返回类型而是返回等价的优化后工作流。从源码结构看chain在 celery/app/builtins.py 中被实现为一个占位任务其run方法直接抛出NotImplementedError(chain is not a real task)真正的语义由画布canvas模块在构造工作流时处理——这印证了chain()是一个语法糖而非独立可执行任务其返回类型取决于整体工作流的优化结果。测试工具增强新的 pytest fixtures4.0.x 系列为测试体系新增了两个 fixture4.0.1新增celery_parametersfixtureIssue #3626由 Steffen Allner 贡献允许在测试中使用自定义的Celery初始化参数4.0.2新增celery_worker_paremetersfixture由 Michael Howitz 贡献注意拼写为paremeters用于定制 worker 的启动参数。这两个 fixture 补充了原有的测试基础设施见 celery/contrib/testing/ 目录下的app.py、worker.py、manager.py、mocks.py等模块让集成测试可以更灵活地控制应用与 worker 的初始化方式。升级到 4.0.x 的检查清单综合 4.0.x 系列的变更从旧版本尤其是 3.1升级时建议逐项核对立即升级到 4.0.14.0.0 的默认accept_content不安全CELERYSA-0003务必升级或显式设置app.conf.accept_content [json]重命名数据库结果后端设置sqlalchemy_*→database_*4.0.0rc7 起旧名完全不生效不要依赖chain()的返回类型chain(A, B, C)现在等价于A | B | C可能返回 group 或其他优化后的类型使用app.register_task注册类式任务旧式类任务注册方式已被新 API 取代Issue #3615新项目推荐app.task检查 Redis 结果后端配置如需连接超时控制使用新增的redis_socket_connect_timeout关注序列化安全worker 默认只接受 JSON 消息如与旧版多语言客户端互通需显式扩大accept_content。以上所有变更细节均可在仓库 docs/history/changelog-4.0.rst 中溯源对应的实现证据分散于 celery/app/base.py、celery/app/defaults.py、celery/backends/redis.py、celery/result.py 等源码文件。【免费下载链接】celeryDistributed Task Queue (development branch)项目地址: https://gitcode.com/gh_mirrors/ce/celery创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考