Service Fabric

SF同其它框架的差异点,主要在于以下几个设计原则上:

  1. 纯分布式
  2. 状态的强一致并且可扩展
  3. 支持stateful的service,这里application默认的模式基本都是一主多从的有状态服务,所以论文里面提到的data aware,主要是 a. 放置或者routing时候,对于主或者从的选择, b. fail over时候的策略

Layered Desgin

基于上面两个最重要的需求,SF本身分成两个层次来解决这个问题

  1. Federation System: 解决两个最关键的问题,系统节点的状态和通信的路由问题
  2. Reliability System: 解决Service相关的问题,例如如何放置,Service replica,Failover的选择
Service Fabric_第1张图片
15305958495419.jpg

Federation System

这一层算是整个SF最核心的部分,主要解决对于系统状态的强一致性共识。系统状态包括:

  • 处理某个服务(Key)的节点在哪
  • 整个SF中节点的状态
  • 一个application的集群的状态:例如leader是哪个

SF Ring

从逻辑上,整个SF的世界可以抽象成一个SF Ring的结构,一个SF Ring具备2^128个节点,Node和Key都会被Map到这个Ring上的某个点。

因为SF从设计上需要避免对于单节点的依赖,所以Ring上的一个Node的邻居们,就需要负责Node之间的Failure Detection,Membership管理等职责

Failure Detection & Membership Management

因为SF通过Ring上的邻居们相互监督,所以设计中的强一致性状态,指的也是这一批邻居中对于节点的存活和系统成员的认识是一致的。

SF这里将Membership的维护分成了两个部分:

  1. Failure的探测

    一个Node会有一个Monitor Set,基本上就是它在Ring上的邻居,为了保证强一致性,所有Monitor都必须对同一个节点的状态有共同的认识。所以这个Node需要在所有Monitor上都申请一个Lease,在Lease期间,Monitor保证不会认可提出它。同时一个Node需要从整个Monitor Set中获取Lease,一旦一个Node无法在Set中获取到所有的人的租约,这样就会自己提出退出Membership。

    在Ring上相邻的X和Y两个Node,一般都会互相为Monitor。这样会在相互的状态上认知产生冲突。例如X,Y可能相互认为对方已经离线,分别要求对方被踢出集群。

  2. Failure的决策

    为了达成分布式节点的一致性,总而言之有两种做法,一种是通过多数成员同意,另一种就是交给别人裁决。SF这里采用了后一种方式。

    SF里面有一个特别的服务,Arbitrator用来裁决Failure的提议,所有成员节点可以通过自己的观察进行猜测,产生提议,最终在Arbitrator进行决定。

    Arbitrator本身也是一组互相独立运行的集群,通过quorum方式运作,基本上等同于一个RSM。说白了就是要序列化对于集群状态的修改,例如假设A和B都认为对方挂了发出踢出对方的请求,那么Arbitrator最大的作用,就是确定那个提议为先而生效。

Route

SF的路由表类似Chord,已指数为步长记录相邻的节点,例如Node K记录 距离为 K + 1, K + 2, K + 4 ...的节点,不过SF的Route是对称的,顺时针方向和逆时针方向都记录。

所以一个Key的寻址,首先是查找它在Ring上的对应的值K,然后通过递归方式,每个节点查询自己所知的节点里面离K值最近的节点,直到查找到最终归属的节点。

所以在路由这方面,分为两部分状态需要维护

  1. Node在Ring上的位置

    这里的一致性分为两部分:

    • 邻居的状态,是强一致的
    • 其它节点,通过类似gossip的方式获取变化,最终一致性
  2. 一个Key属于哪个Node

    SF中每个Node会持有一个Token,对于一个Ring上的一个值,同时保证

    • Safetyness: 一个时间点,对于一个Key最多一个Token持有者
    • Liveness: 最终总会有Token接管这个Key

Leader Election

对于一个Key,Leader Election是隐性的,就是持有这个Key所属Token的那个节点。这个极大的简化了Leader变化的处理,减少了Leader变化带来的可用性丢失的时间。

RELIABILITY SUBSYSTEM

在Federation对于系统有了强一致的共识之后,之上的子系统主要解决放置,Replication,HA等

问题

  1. 和别的平台有啥不同,优点在哪?

    SF最大的设计目标感觉在于两个点;第一,支持大规模的集群;第二,支持Stateful的Service

    针对集群规模的问题,传统由一个Master负责整个集群管理,这样可以保证状态的强一致。最大的问题在于这个Master成为整个系统的瓶颈,另外也会带来因为其网络的波动导致了大量节点被踢出的问题。另外一个类似Serf这种,通过gossip方式来最终一致,问题是存在一个时期的不一致,需要一个anti-entrophy的过程。SF使用了一个较小规模的Membership的Group来维护强一致的状态,结合数据Token的方式,从而使得整个整个系统状态是强一致的(这个挺有意思,基本结合了Eventual Consistency的Long Distance的路由,加上Strong Consistency的Short Distance的路由,从而使一小部分的强一致的状态,变成了整个Ring的强一致状态)。另外SF使用的Full Membership和O(log(n))的路由结合的方式,也保证了集群的扩展性。

    针对第二个问题,首先对比一般只支持stateless,带来的额外挑战在于为了HA,一个Service需要一个Replica Set, 那么对于写请求,需要路由到相应的Primary的Service上,另外在Fail Over的过程里面,平台也需要知道有哪些Secondary的replica,可以重新选择一个作为Primary。这个问题感觉最大的挑战就是在于Failover等主从swap时候路由更新的问题,SF这里通过路由的方式解决,一个Key始终通过持有负责它的Token的Node进行路由,也是极大的减少了在这个过程里面,系统达到稳定状态需要广播的路由。

  1. 路由的单位应该是Service,但是SF中Service是通过指定Key的方式进行放置的,这个如何实现呢?

    大概是通过PLB给Service分配了Key吧,因为无法通过简单Hash解决负载均衡的问题,另外放置一个service也有诸多限制。

    所以这个路由应该要向FM获取Service的Key

  2. 支持stateful的service有意义么

    哪些application是无状态的呢,无非是把复杂度往哪推罢了。。

    有时候使用有状态服务可能比依赖外部DB,或者QUEUE更简单的情况是复杂的限制情况,不太好用现有的数据组件处理(例如write skew),与其依赖复杂的分布式锁,还不如直接做成有状态的简单一点。。。

你可能感兴趣的:(Service Fabric)