Serf:Gossip Protocol

Serf使用Gossip Protocol来广播消息到集群中。本文介绍这个内部协议的细节。gossip协议基于“SWIM: Scalable Weakly-consistent Infection-style Process Group Membership Protocol”,有一写小的适配,很大程度上增长了传播速度和收敛速率。node

SWIM Protocol Overview

  Serf以加入一个已存在的集群或者启动一个新集群开始。若是启动一个新集群,其余节点则会加入它。为了加入现有集群,新节点必须至少分配一个已经存在的节点的地址。新的成员与现有成员经过TCP作一个完整的状态同步而且开始gossip它的存在到集群中。网络

  Gossip基于UDP而且具备一个可配可是固定的扇出(fanout)和间隔。这保证网络资源使用是固定的,不论节点数有多少。经过TCP随机的与一个节点周期的进行完整状态交换,可是远远少于gossip消息。全状态交换和合并会增长成员关系列表收敛的可能性。全状态交换的间隔是可配的或者彻底中止。性能

  故障检测经过可配间隔的周期性的随机探测实现。若是节点在一个响应时间内(一般是RTT时间的倍数)没有进行ack,会尝试间接探测。间接探测要求可配数量的节点来探测相同的节点,以防网络问题致使咱们的节点探测失败。若是咱们的探测和间接探测都在响应时间内失败,则该节点被标记为“suspicious”而且会被gossip到集群中。一个可疑节点仍然视为集群的成员。若是集群的能够节点在一个可配的周期时间内对怀疑没有争论,则节点最终被认为死亡,这个状态被gossip到集群中。排序

  这是对协议的一个简短和不完整的描述。更好的方式是完整阅读 SWIM论文和Serf的源代码。事件

SWIM Modifications

  如前所述,gossip协议基于SWIM,可是包含小的变化,很大程度上增长了传播速度和收敛速率。ip

  SWIM的变化都记录在这:ci

  • Serf经过TCP按期的作完整状态同步。SWIM只经过gossip传递消息。虽然最终都是一致的,可是Serf能够更快速的收敛,以及优雅的从网络分区中恢复。
  • Serf有一个从故障检测协议分离出来的gossip层。SWIM只经过在probe/ack消息上附带gossip消息。Serf基于专用的gossip消息传递。这个特征容许你有一个更高的gossip速率(例如200ms一次)和更低的故障检测速率(例如每秒一次),使得总体更快的收敛速率和数据传播速度。
  • Serf保持死亡节点设置为死亡的时间,因此当完整的同步请求时,请求者也接收死亡节点的信息。由于SWIM不作完整同步,而且SWIM一旦知道节点死亡则当即删除节点状态。这个改变再一次帮助集群收敛更快。

Lifeguard Enhancements

  SWIM假设本地节点是健康的,也就是说能够软实时处理数据包是可能的。然而,在本地节点正在经历CPU或者网络资源耗尽的状况下,这个假设就不成立了。结果是会致使节点健康偶尔振动,致使错误的监控报警,增长遥测噪声,而且直接致使整个集群浪费CPU和网络资源来诊断一个可能并不存在的故障。资源

  Serf 0.8版本添加了Lifeguard,它彻底解决了这个问题经过加强SWIM。get

  第一个扩展是引入了“nack”消息来探测查询。 If the probing node realizes it is missing "nack" messages then it becomes aware that it may be degraded and slows down its failure detector. As nack messages begin arriving, the failure detector is sped back up.同步

  第二个变化是引入了在声明另外一个结点故障以前动态改变怀疑超时时间的功能。探测结点初始化时有一个很长的怀疑超时。只有集群中的其余节点确认一个节点是能够的,计时器加速。在正常操做期间检测时间实际上与早期版本的Serf同样。然而,若是一个节点被退化,而且没有获得确认,则会有一个很长的超时时间来容许被怀疑的节点来反驳它的状态而且保持健康。

  这两个机制联合使得Serf对于集群中退化的节点更加健壮,同时保持故障检测性能不变。Lifeguard没有额外的配置,它自动调节。

Serf-Specific Messages

  在基于SWIM的gossip层上,Serf发送一些自定义的消息类型。

  Serf大量使用Lamport clocks来维护消息的顺序,虽然最终是一致的。每一个由Serf发出的消息都包含一个Lamport clock时间。

  当一个节点优雅的离开集群时,Serf经过gossip层发送一个leave intent。由于gossip层如下不区分节点离开集群和一个节点被检测为故障的,这容许更高级别的Serf层来检测故障与优雅的离开。

  当一个节点加入集群时,Serf发送一个join intent。这个意图的目的仅仅是绑定一个Lamport clock时间到join上使得在leave乱序来临时,join能够被正确的排序。

  对于自定义的事件和查询,Serf发送user event或者user query消息。这个消息包含Lamport时间,事件名称和事件负载。由于user event是沿着使用UDP的gossip层发送,负载和整个消息帧必须知足在单个UDP包内

相关文章
相关标签/搜索