框架层连接管理、心跳机制+优雅退出来保证无异常流量
一、问题分析
plus平滑发布过程中出现的发布节点错误接收客户端流量问题,一度被认定为mns下发服务状态慢导致。因而得出一个粗放的结论:解决流量异常只能提升mns下发服务数据的速度,即保证客户端感知服务状态一致性。这其实是一个不严谨的定论,下面重新定义问题。
A:mns下发状态慢,客户端感觉服务状态变动不及时
B:服务端流量摘除异常,发布节点接收异常请求
应该明确这是两个不同的问题,它们不是绑定关系,因而不能同等看待。先给结论,出现mns下发状态至客户端慢问题时,也能够避免服务节点错误接收流量现象。
A、B两个问题的处理方案不应混为一谈的原因如下:
1.流量摘除本质是连接管理问题,在通信框架层面进行处理更合理,第三节将进行分析
2.mns注册中心是一个AP系统,难以兼顾客户端状态一致这样的CP需求,2.1节详述
3.服务状态变更需要客户端进行感知,优化mns数据扇出(Fan-Out)性能后仍将存在一段数据分发真空期,难以杜绝流量异常case可能性,2.2节详述
ok,我先说明提升mns数据下发速度,进而保证客户端感知服务状态一致性,所存在的挑战性。
二、注册中心定位
2.1 AP系统
CAP是分布式系统中一个重要的理论:分布系统的一致性(C)、可用性(A)以及分区容错性(P),三者不可兼得。设计分布式系统时,常常是在CP与AP之间针对业务场景进行权衡(trade-off)。
通过调研业界多个注册中心后发现大家的结论一致:注册中心是AP系统而非CP系统;也即注册中心关注的重心是整体的高可用+性能,并且会牺牲部分一致性。诸如ConfigServer(阿里)、Eureka(Netflix)认为注册中心使用Zookeeper这样强一致性的组件,是错误的用法。业界对于注册中心的定位是高可用、高融灾的AP系统,甚至容忍因客户端感知服务状态不一致,带来的流量异常。
在此,不深入讨论注册中心使用ZK的否合理性;但是注册中心是AP系统的结论得到广泛认可,即保证高可用和性能,注册中心本身会出现个别客户端感知服务状态不一致现象。
2.2 mns状态分发
mns体系的状态下发包括两类网络传输:notify,通知代理组件服务状态发生变动;pull data,代理组件获取变动后的服务信息。感知状态信息的客户端机器处于不同网络环境,存在诸多不可控因素,直接影响mns状态下发的时长。此外,mns状态分发涉及zookeeper、mnsc、sg_agent、mns-invoker等多个组件交互、链路长,任何组件的抖动都会影响mns整体分发时间的稳定性。一方面服务数据传输必然需要时间段,另一方面分发时间的整体稳定性不可控,难以杜绝流量异常case可能性。
总结,结合注册中心AP系统的定位,强制mns在一个稳定+可预期的时间段内,完成针对所有客户端的服务数据分发具有很高的挑战性,甚至限制mns本身的演进方向。
最后,流量异常是连接粒度的控制,从通信框架入手解决更容易。完全依赖注册中心优化来处理这个问题,会增加解决方案的复杂度,甚至影响整个mns的稳定性,得不偿失!
三、解决方案
正如第一节提及,mns状态下发慢和流量异常输出是两个问题。mns本身的感知慢问题必须解决,但不是处理流量异常的根本方案。我们如果能够破坏B现象形成的必备条件,就能够解决流量摘除异常问题。先看下流量异常复现必备的条件:
1.发送请求前,连接正常:服务端发布节点关闭进程后,因为有连接状态检测,新的请求不可能发送到已经关闭的port。
2.数据返回时,连接关闭:服务接收到请求后,进程被关闭,处理后的response无法返回给用户。
针对以上条件,接着说明plus平滑发布过程中流量异常问题的通信框架处理方案:
1.连接管理:通信框架完善连接状态管理机制,保证服务端close socket后不再向服务端发送请求。
2.优雅退出清理机制:框架层面开启统一协议心跳,开始服务发布关闭进程前,通信框架关闭心跳包响应机制;客户端感知心跳检测失败,进而主动剔除即将下线的服务节点连接。2个心跳周期后进行实际的资源清理和进程关闭工作。这样可以避免流量进入服务节点,却无法返回调用端的问题。
3.调整心跳频率,目前10s一次的心跳周期太长,适当降低心跳探活周期,能够配合以上方案避免流量异常问题出现。
总结来说:这个方案通过通信框架自身的心跳机制+优雅退出,破坏了节点接收异常请求出现的必备条件,解决流量摘除问题。方案针对性强,可行性高。