C++分布式实时应用框架——状态中心模块
技术交流合作QQ群:436466587 欢迎讨论交流
版权声明:本文版权及所用技术归属smartguys团队所有,对于抄袭,非经同意转载等行为保留法律追究的权利!
状态中心是分布式系统中不可或缺的部分。一个分布式系统动辄上百个节点,这些节点相互间通讯关系的建立和维护;运行时每个节点的实时状态数据采集和上报;系统管理模块下达集群管理命令时,命令如何传达到具体节点;集群节点故障时,如何检测发现并及时进行处理,从而避免对集群运行产生影响。这些都是在分布式实时系统设计时需要考虑的功能性问题。更不用说,分布式环境下的数据一致性、二阶段提交、脑裂、集群选主等复杂的分布式原生问题。状态中心就为了解决这一系列问题而诞生的,是CDRAF(Cpp Distributed Real-time Application Framework)之所以能称为“分布式”框架的核心和关键。
一、状态中心模块构成
状态中心主要由两个模块组成。一是运行于多台主机或者节点上的分布式状态中心集群(Distributed Status Center Cluster:DSCC)。DSCC上存储了应用集群所有节点的状态数据,节点间的连接关系,甚至做为管理命令的中转站。之所以需要部署在多个节点是为了解决分布式环境中的单点问题。并且由于数据存储了多份拷贝,DSCC还解决了数据一致性、二阶段提交、脑裂、集群选主等复杂的分布式原生问题。另一个模块是运行于分布式系统各个节点上的状态中心代理(SmartAgent),SmartAgent主要负责上面提到的分布式系统的功能性问题,包括:从DSCC上获取节点间通讯关系,建立分布式集群的通讯连接,并实时接受变更,动态地为集群增加或者删除节点;采集每个节点的实时状态数据并上报到DSCC;从DSCC上接收系统管理模块下达的管理命令并执行。下图浅绿色部分很好地诠释了这一架构。
二、事件机制
分布式状态中心集群(DSCC)通过事件机制与每个节点上的状态中心代理(SmartAgent)保持信息联系。当节点上SmartAgent对DSCC上的某个数据感兴趣,就会到DSCC上注册一个这个数据的通知。一旦DSCC上这个数据发生变化,相应注册了通知的SmartAgent就会立刻接受到这个数据的变更通知。正是这一机制保证了分布式系统数据接收的实时性,并且避免了轮询等其它方式产生的弊端。事件通知功能,是整个状态中心功能的基石,其贯穿了状态中心的各个功能模块。如:当某个计算节点运行状态发生变化,状态中心中对应于该节点状态数据即会发生变化,此时状态中心向关心此事件的SmartAgent进程发出一个状态改变的事件通知消息,消息中携带了状态数据变化节点的主机名以及事件类型信息,以供SmartAgent进程获取进行相关处理操作。
SmartAgent初始化时,需要对其在DSCC上感兴趣的数据进行注册,由于业务的复杂性,这类数据会非常之多。在设计时候,考虑到分布式系统的复杂性,以及功能的多样性。将事件消息处理模块设计为职责链模式,链上的每个节点都对应于CDRAF的某一功能。采用这样的设计,极大了方便了CDRAF功能的扩展,在研发CDRAF过程中加入新的功能时,只要定义相关的消息,再写好对应此消息的处理代码即可。
三、状态上报
当集群某个节点启动时,由运行在此节点上的SmartAgent进程主动向DSCC上报本节点的属性数据,这些数据有:节点的IP、对外提供各类服务所对应的端口号、节点的业务类型、主机名(设置于环境变量)、节点的运行状态(正常、停止,启动中、故障等)、当前节点的处理能力(CPU、TPS、时延等),这一系列用来描述当前节点的数据。当SmartAgent获取到这些数据后,会周期性地将这些数据上传到DSCC中。其它节点的SmartAgent和系统管理模块便可以不断取得这些更新的数据。
四、服务发现
对于一个分布式集群而言,集群的节点数是可以动态扩缩容的。不同类型的业务节点对外开放的端口也是会发生变化的。按传统的做法,为每个服务访问者配置服务地址列表到本地已不再可行。目前docker容器部署技术的火热发展,很多企业的业务应用正在向docker部署转移,已不再是部署在物理机或是虚拟机上。而我们知道docker容器在启动前IP是未知的。基于这一系列的分布式系统特点,为CDRAF提供一个节点运行时服务注册中心与发现功能就成了一个必须的要素了。DSCC所具有的内部存储功能,可以很好的解决这一问题。当集群新增一个节点时,新节点向DSCC进行注册后,集群原有的其它节点便可以从DSCC中得到新节点地址和端口等信息,并与之建立新的通讯关系。
五、容错机制
CDRAF中对于每个节点的健康状态进行了管理,节点实时上报健康状态,并且节点与状态中心间有心跳机制。如果节点因业务故障主动告知状态中心故障状态,或因网络中断、停电、主机故障等被动原因,节点在一定时间间隔内没有主动上报健康状态。状态中心将把自己内部所存储的该节点状态描述设置为故障,并向集群中关心该节点的其它节点发送故障事件消息。其它节点在收到消息后即将消息中标记的该故障节点所自己的业务链中移出。防止其它节点继续向故障节点发送消息,导致消息处理失败。如果业务链中没有该故障节点的备用节点,系统管理模块将自动拉起一个新的节点以接替故障节点,注意在容器环境下,拉起一个新节点往往比重启一个节点来得迅速,从而保障系统的正常运行。
六、优雅启停
优雅启停功能主要是为了解决集群中某个节点退出(从网络中退出,或主动缩减节点)集群时,该节点消息队列里可能还有未处理的消息。如果直接将连接断开,那很有可能会丢失一定数量的未处理消息。虽然某些系统可以接受这样的丢消息故障,只要分发节点在一定时长内没收到响应消息就重新发送丢失的消息即可。但是这样的处理,会对分发节点造其它的问题。所以在CDRAF是我们设计了“优雅启停”这一节点主动退网功能。
当节点要进行退网时,状中心会接收到相关的操作命令,状态中心DSCC将此命令转化成统一的事件,发送给相关的消息发送节点上的SmartAgent进程。SmartAgent进程收到事件消息后。通知本地的通讯平台的通讯监控程序。这时消息发送节点上的消息发送的进程将停止向将要退出网络的节点发送消息,并断开发送消息的连接。但是此时将要退出网络的计算节点仍在处理消息,并且处理结果通过和消息发送节点的接收连接发送回去。也就是说,这里的关键是在消息发送节点与处理节点间建立了双通道的网络链路。对于消息发送节点而言,一类链路用于发送消息,另一类链路用于接收消息。当业务节点处理完自己消息队列里所有消息时,业务节点主动断开返回的消息连接。这样就实现了不丢消息的退网功能。
未完待续……