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

Mingle

在 Celery 的介绍中,Mingle 主要用在启动或者重启的时候,它会和其他的 worker 交互,从而进行同步。同步的数据有:

  • 其他 worker 的 clock
  • 其他 worker 已经处理掉的 tasks

这其实也就是它的所有功能的,所以你可以猜测功能应该很简单吧?不妨一起来看看,最开始还是回忆一下第一篇文章中的 Bootstep,所以我们可以毫无压力得找出源码所在的文件:

这里从注释中可以很简单得看出 Mingle 的作用,然后初始化也是比较简单,关键还是 Line 37start,需要我们关注 sync 做了什么,为什么上来二话不说就 sync?其实上来就 sync 很好理解,毕竟 Mingle 的作用就是进行 sync 嘛,所以我们要关注的是如何实现的:

这里原来的代码有点冗余,我给忽略掉了,直接上精简后的代码,所以你可以很清晰得看到代码的逻辑是这样的:

  1. Mingle 向每一个 Worker 发送问候:hello
  2. 每个 Worker 都向 Mingle 回复自己的信息(clock 和 tasks)
  3. Mingle 更新自己的信息

这些逻辑我们从精简后的代码可以简单看出来,所以就不细说了,但是有一点需要展开讲讲,那就是 Line 47 中的 inspect.hello,这应该是 第五篇 的内容,但是,之前只是介绍了一下如何注册,并没有对这些命令一一解析,所以这里用到了,我们就不妨看看里面的内容。

ok,这里我们可以看到在 Line 319、320 就返回了两个东西,分别是:

  • revoked:当前 worker 记录的已被完成的 tasks
  • clock:当前 worker 的 clock

然后就返回到刚起来的 worker 了,收到这个消息的 worker 就根据这两个信息刷新自己的状态,然后继续运行,Mingle 也就完成了自己的任务了。

Gossip

和 Mingle 不同,Gossip 却是消费 Event 的,本来按道理应该放在 第六篇 中介绍,但是由于篇幅原因,所以一起放在这里来说了,不多赘述,我们直接看 Bootstep

由于 Gossip 的初始化内容太多,所以我也不全都展开了,挑了些重点(还是很多),但是目前我们可以忽略大部分的内容,最先需要关注的是 Line 24,如果你够细心的话你会发现这个 Bootstep 和其他不一样,因为它继承的是 ConsumerStep,这是会注册一个 Consumer 的!

然后我们没啥好看了,所以按照套路还是看看 start 呗,然而它调用的也是父类的 start,所以,没办法咯,直接跟过去:

诺,是这样吧,是增加了 Consumer,这样的话,我们就必须看看这个 Consumer 是什么了,能够消费什么样的数据:

好,这样就清晰了,所有关于 worker.# 的 Event 都被这里消费了,这里算是看完了。

那现在的问题变成了这些 Event 都是从哪里过来的,我们有必要对源头进行一下追踪,但是,怎么追踪呢?回想一下 第六篇 中讲 Event 的消息传递的那里,再和这里一对比,事情就很清楚了。

你以为 Gossip 就这么结束了么?嘿嘿,那你就被 Celery 给蒙骗了,悄悄告诉你,Celery 在 Gossip 中埋伏了一个厉害的功能,但是没有对外宣称,那就是 Leader 选举!,不信?我带你去看看:

这是选举的入口,先不解析代码,我们先来看看有谁调用了它:

ok,可以发现这有个 control 命令用到了它,这里有注释,我们可以看到参数分别代表的意思:

  • id:唯一的标识,用于识别一次选举
  • topic:本次选举的 topic,其实是标识 action 的类型
  • action:本次选举的目的,选中的 leader 负责处理这个 action

那么这样我们就清楚了,首先,有一个 action 需要执行,但是,那么多的 worker,交给谁执行呢?这就需要进行 选举,那么选举的方式是怎么进行的呢,我先用一张图来描述一下这个过程:

  1. control 表示需要进行一个选举,然后一个 worker 的 gossip 就发送了一个 Event:worker-elect,然后所有的 Worker 都能接收到:

  2. 每个 Worker 接收到之后,就对这个选举进行响应,将自己的选号(clock)送过去,这样,每个 Worker 在发送选号的同时,也接收到别人的选号,因为收发的路线太多,我就找一个 Worker 来表示收,但是其他 Worker 也是有收的,只是我没有标出来:

  3. 当一个 Worker 收到所有 Worker 的 ACK 之后,那么它就会对所有的 Worker 的 选号 进行排序,选出其中 最大的选号 作为本次选举的 Leader,如果 Leader 是自己那么就处理这个 Action,如果不是自己,那么忽略,应该被选中的 Leader 也在执行这个过程,所以不需要别人担心。

这就是实际执行的示意图,对应到代码就分别是:

  1. 第一步中的 Control 要求选举和发送选举 Event 我们前面已经看过了
  2. Worker 收到选举 Event 之后,发出自己的参选声明:

  3. 每个 Wroker 对别人回应的参选信息进行选举:

ok,整个流程就是这样的了,那么问题来了,万一有一个 Worker 收不到 replies 或者发出的 reply 不小心丢了会怎么样?是不是整个选举过程就进行不下去了?我好像没有看到 Celery 有在这方面做一些努力。

Celery 源码解析七:Worker 之间的交互的更多相关文章

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

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

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

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

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

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

  4. QT源码解析(七)Qt创建窗体的过程,作者“ tingsking18 ”(真正的创建QPushButton是在show()方法中,show()方法又调用了setVisible方法)

    前言:分析Qt的代码也有一段时间了,以前在进行QT源码解析的时候总是使用ue,一个函数名在QTDIR/src目录下反复的查找,然后分析函数之间的调用关系,效率实在是太低了,最近总结出一个更简便的方法, ...

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

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

  6. jQuery 源码解析(七) jQuery对象和DOM对象的互相转换

    jQuery对象是一个类数组对象,它保存的是对应的DOM的引用,我们可以直接用[]获取某个索引内的DOM节点,也可以用get方法获取某个索引内的DOM节点,还可以用toArray()方法把jQuery ...

  7. Celery 源码解析八:State 和 Result

    在前面几篇解析中,我们已经看过了 Worker 是如何运行的,Task 是如何创建的,以及怎么被路由到 Worker 中,除了这些之外,我们还对流量限制,Worker 控制和 Task/Worker ...

  8. ReactiveSwift源码解析(七) Signal的CombineLatest的代码实现

    本篇博客我们就来聊一下combineLatest()的使用以及具体的实现方式.在之前的<iOS开发之ReactiveCocoa下的MVVM>的博客中我们已经聊过combineLatest( ...

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

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

随机推荐

  1. Chloe.ORM框架应用实践

    Chloe.ORM 是国人开发的一款数据库访问组件,很是简单易用.目前支持四种主流数据库:SqlServer.MySQL.Oracle,以及Sqlite,作者为这四种数据库划分出了各自对应的组件程序集 ...

  2. web容器启动后自动执行程序的几种方式比较

    1.       背景 1.1.       背景介绍 在web项目中我们有时会遇到这种需求,在web项目启动后需要开启线程去完成一些重要的工作,例如:往数据库中初始化一些数据,开启线程,初始化消息队 ...

  3. 反射型 DDoS 攻击的原理和防范措施

    随着僵尸网络的兴起,同时由于攻击方法简单.影响较大.难以追查等特点,分布式拒绝服务攻击(DDoS,Distributed Denial of Service)得到快速壮大和日益泛滥. 成千上万主机组成 ...

  4. 博客发在win10.me

    看到了http://www.win10.me/?page_id=58 说可以把自己的文章投给win10.me 我试试 抱着没有的心态 居然可以 我联系九幽,和他们说我写了很多博客,质量不好,他们说好 ...

  5. win10 UWP 全屏

    win10 可以全屏软件或窗口,窗口有一般.最小化.最大化.我们有新的API设置我们软件是全屏,是窗口.我们可以使用ApplicationView让我们软件全屏,取消. 下面是一个简单的例子,判断我们 ...

  6. bootstrap学习之利用CSS属性pointer-events禁用表单控件

    参考链接: CSS3 pointer-events:none应用举例及扩展 首先pointer-events在除去SVG中的应用只有两个值:AUTO | NONE pointer-events:non ...

  7. Redis 学习笔记-应用场景

    Redis作缓存系统 Redis可以对每个键设置生存时间 可以限定数据占用的最大内存空间,在数据达到空间限制后可以按照一定规则自动淘汰不需要的键. 设置方法: 修改配置文件的maxmemory参数,限 ...

  8. Hadoop Streaming详解

    一: Hadoop Streaming详解 1.Streaming的作用 Hadoop Streaming框架,最大的好处是,让任何语言编写的map, reduce程序能够在hadoop集群上运行:m ...

  9. Nodejs.安装.非源码方式安装Node.js (Centos)

    已验证的适用环境: Centos6.x 树莓派官方ROM(Raspbian) 先去官网下载已编译好的安装包 https://nodejs.org/en/download/current/​ 以Cent ...

  10. typeof、constructor和instance

    在JavaScript中,我们经常使用typeof来判断一个变量的类型,使用格式为:typeof(data)或typeof data.typeof返回的数据类型有六种:number.string.bo ...