在前面几篇解析中,我们已经看过了 Worker 是如何运行的,Task 是如何创建的,以及怎么被路由到 Worker 中,除了这些之外,我们还对流量限制,Worker 控制和 Task/Worker 产生和处理 Event 进行了介绍。但这却不是全部,今天我将继续和大家一起来看看 Celery 的 Task Result 和 State 相关的内容。

Task State

celery/celery/states.py 中,可以看到 Task 的所有 State

至于如果想要看 Task 的状态转变,那我们就需要回顾一下 Task 从产生到完成的过程,如果是一个普通的 Task 的话,那么它的执行流程应该是:

从 Producer 产生 -①-> MQ -②-> Consumer 接收 -③-> 执行策略执行 -④-> 执行完成

那么这里的 ①②③④ 有没有设置状态,并且状态是啥,就是我们关注的重点了,ok,那我们就跟随之前的脚步快速得发掘一番:

这个是同步发送消息的时候,其实也是第一次出现 state 的时候,但是这个 state 已经是 ④ 之后的状态了,但是,无妨,我们已经知道了执行完成之后的状态是在这里 update 的。那么对于异步的情况又是如何更新状态的呢,那根据我们之前的 review,我们知道应该去找 AsyncResult

所以这里就是 backend 的事情啦,backend 再甩锅给 backend Consumer,然后就是在 backend Consumer 里面干活了,最后就到了这:

这里其实虽然是调用的 on_state_change 但是,我们应该知道的一点就是在这个时候其实状态已经变化了,那么我们就应该追述到上面的 result._iter_meta,看看里面的实现,这里我就飘过很多细节了,直接看最实际的地方:

这里可以发现,其实结果是通过 Backend 组件完成的,例如 Redis 就放在 Key 对应的 Value 中,其他的 Backend 也类似,如果没有的话,在 Line 667 我们就知道了,状态就是 PENDING 啦,第二个状态捕获!然后还有 Line 668 这里的解析结果也是值得我们一看,我直接看最后吧:

可以发现这里也是很有趣的,如果 Task 的状态是异常状态的话,还需要进行异常回溯,其实就是把异常信息解压出来,展示给我们看。

那我们是时候我们去找找第三个状态:Received 了,我们可以猜测一下大概可能出现的位置,这里就是:

这里可以发现居然是有一个 EVENT 发送出去,然后我们就应该去看看处理这个 Event 的人啦,如果你还有印象的话,那么你应该可以很容易得追踪到:

这里你会发现你感兴趣的所有东西,哈哈,其实你需要看看一个字典:

你会发现所有的状态都可以在这里更新,哈哈。所以下面我就列一下各个 EVENT 的发出地点就好了:

如果你够细心的话,你会发现 failedsucceeded 都是有两处发送地点,有兴趣猜测一下原因么?

Task Result

其实在前面说 State 的过程中我们已经看到了很多和 Result 有关的东西了。Result 可以认为就两种,同步和异步的,其实也可以看成一种;但是,从另一个维度看,Result 其实也可看成成功的和失败的,anyway,这些都是在 Result 中保存了的。

我在这里就简单回顾看看 第三篇 中看过的内容,其实 Result 中就放了这几样东西:



分别是 任务ID返回值执行状态 以及 错误堆栈信息,我们在调用的地方用这些信息就足够了。

Worker State

除了 Task 有状态之外,Worker 其实也是有状态的,回顾我们 第一篇 的内容,Worker 的启动过程这么冗长,所以不是说一运行就到了 Runing 状态了,中间肯定是有各种状态的,所以我们不妨一起来看看。

回顾一下我们之前看的一些代码,我们应该是有讲过一个叫做 HeartBeat 的组件,它的作用就是保持发送心跳,告诉其他 Worker 这个 Worker 还活着,那么这是一种状态,除了这些状态之外,我们还可以找到的其他 Worker 状态有:

  • worker-offline
  • worker-online
  • worker-heartbeat

Worker-heartbeat 我们很清楚它在哪里发送出去的了,那么 Worker-onlineWorker-offline 又是在哪里发出去的呢?其实都一样的,我们看到 Heart 这个 Bootstep

着重看看 startstop 方法,我们会发现其实调用的都是同一个地方:

一切了然于胸!

Celery 源码解析八:State 和 Result的更多相关文章

  1. Celery 源码解析三: Task 对象的实现

    Task 的实现在 Celery 中你会发现有两处,一处位于 celery/app/task.py,这是第一个:第二个位于 celery/task/base.py 中,这是第二个.他们之间是有关系的, ...

  2. Celery 源码解析五: 远程控制管理

    今天要聊的话题可能被大家关注得不过,但是对于 Celery 来说确实很有用的功能,曾经我在工作中遇到这类情况,就是我们将所有的任务都放在同一个队列里面,然后有一天突然某个同学的代码写得不对,导致大量的 ...

  3. Celery 源码解析六:Events 的实现

    在 Celery 中,除了远程控制之外,还有一个元素可以让我们对分布式中的任务的状态有所掌控,而且从实际意义上来说,这个元素对 Celery 更为重要,这就是在本文中将要说到的 Event. 在 Ce ...

  4. Celery 源码解析七:Worker 之间的交互

    前面对于 Celery 的分布式处理已经做了一些介绍,例如第五章的 远程控制 和第六章的 Event机制,但是,我认为这些分布式都比较简单,并没有体现出多实例之间的协同作用,所以,今天就来点更加复杂的 ...

  5. Celery 源码解析四: 定时任务的实现

    在系列中的第二篇我们已经看过了 Celery 中的执行引擎是如何执行任务的,并且在第三篇中也介绍了任务的对象,但是,目前我们看到的都是被动的任务执行,也就是说目前执行的任务都是第三方调用发送过来的.可 ...

  6. jQuery 源码解析(八) 异步队列模块 Callbacks 回调函数详解

    异步队列用于实现异步任务和回调函数的解耦,为ajax模块.队列模块.ready事件提供基础功能,包含三个部分:Query.Callbacks(flags).jQuery.Deferred(funct) ...

  7. ReactiveSwift源码解析(八) SignalProducer的代码的基本实现

    在前面几篇博客中我们详细的聊了ReactiveSwift中的Bag.Event.Observer以及Signal的使用方式和代码实现.那么在接下来的这几篇博客中,我们就依附于之前博客的基础上来聊一聊S ...

  8. [源码解析] 并行分布式框架 Celery 之 worker 启动 (1)

    [源码解析] 并行分布式框架 Celery 之 worker 启动 (1) 目录 [源码解析] 并行分布式框架 Celery 之 worker 启动 (1) 0x00 摘要 0x01 Celery的架 ...

  9. [源码解析] 并行分布式框架 Celery 之 worker 启动 (2)

    [源码解析] 并行分布式框架 Celery 之 worker 启动 (2) 目录 [源码解析] 并行分布式框架 Celery 之 worker 启动 (2) 0x00 摘要 0x01 前文回顾 0x2 ...

随机推荐

  1. Swift 算法实战之路:栈和队列

    这期的内容有点剑走偏锋,我们来讨论一下栈和队列.Swift语言中没有内设的栈和队列,很多扩展库中使用Generic Type来实现栈或是队列.笔者觉得最实用的实现方法是使用数组,本期主要内容有: 栈和 ...

  2. 完美实现身份证校验 js正则

    注意: 1.只针对18为身份证号码进行校验,现在15位的应该很少了, 2.不区分xX大小写, 3.出生年份1900-2099,每月的天数也进行相关验证(考虑的闰月的情况), 4.校验规则详见,这个写的 ...

  3. vim中SnipMate 和 YouCompleteMe 插件触发键 tab 冲突

    花了好几天废了九牛二虎之力终于在win下把ycm插件装上了 然而在配置插件的时候发现snipmate插件与youcompleteme插件会发生tab键冲突 而ycm比较调,直接使snipmate插件完 ...

  4. JDBC基本开发

    JDBC基本开发步骤 一:注册驱动 方式一:DriverManager.registerDriver(new Driver()); //存在注册两次问题,性能较低,消耗资源 方式二:Class.for ...

  5. 异步任务--celery发送邮件

    安装两个python包: pip install celery==3.1.25 pip install django-celery==3.1.17 在配置文件settings.py中做如下配置: a) ...

  6. 基于vip和twemproxy代理实现redis集群的无感知弹性扩容

    目标是实现redis集群的无感知弹性扩容 关键点 1是无感知,即对redis集群的用户来说服务ip和port保持不变 2.弹性扩容,指的是在需要时刻可以按照业务扩大redis存储容量. 最原始的twe ...

  7. 【20171026早】alert(1) to win - 第六、七、八题

    早上7点起床,又写了一篇小说发在了起点网上,有兴趣的可以看看.点击这里 忙完后,继续练习,刚开始发现自己答题的速度有些慢,可能是因为对于html,javascript知识不是很精通,但是话又说回来,谁 ...

  8. 【译】10分钟学会Pandas

    十分钟学会Pandas 这是关于Pandas的简短介绍主要面向新用户.你可以参考Cookbook了解更复杂的使用方法 习惯上,我们这样导入: In [1]: import pandas as pd I ...

  9. 一个fork短码的扩展版本

    原本代码: 链接 int skip = !!fork() + 2*(!!fork()); for (uint32_t i=skip;i!=INT_MAX;i+=4) { } 这个是多进程加速循环的代码 ...

  10. Java基础笔记12

    1.自定义异常. 定义一个类,让该类继承Exception.并写出该类的所有的构造函数.2.IO流. java.io 文件类.File 字节输入和输出流 InputStream OutputStrea ...