线下治理是根据量化分析的结果,对稳定性治理、架构治理等进行调整,下面从链路治理和架构治理相关的实例出发,看看如何通过量化分析指导线下治理工作。
1.链路风险分析的重要性
链路风险分析就是从链路通信的历史数据出发,分析出链路当前存在的风险,减少链路通信的隐患,提高系统的整体稳定性。链路风险分析可以解决的问题域很多,如超时时间设置是否合理、重试次数设置是否合理、服务SLA指标设置是否合理、服务的强弱依赖关系是否符合预期等,服务通信相关的一大部分故障是由于链路风险导致,可以通过链路风险分析的方式提前发现和解决,避免故障的发生。
链路风险分析的基础是链路实时拓扑图和Metric指标,下面会针对几种典型的链路风险,进行详细的分析。
2.超时和SLA风险
客户端访问服务端的超时时间配置,和实际访问情况不符,是非常常见的一种链路风险。上游服务的超时配置过小,会导致一些本来可以正常返回的请求超时,影响服务的SLA和正常的服务体验;超时配置过大,会导致下游服务故障时上游服务超时等待的时间太长,严重时会把整个系统拖垮。因此,超时设置直接关系到系统的稳定性,需要有相应的机制指导服务的超时设置,并及时发现线上系统中的超时配置隐患。
超时配置风险主要有两种:一种是超时时间和实际不相符;还有一种是上下游的超时设置不匹配,比如有A、B、C 3个服务,服务A访问服务B,服务B访问服务C,但实际业务中经常会遇到服务A访问服务B的超时时间比服务B访问服务C的超时时间小的情况。
上述两种超时配置风险均可以通过链路风险分析的方式解决。思路其实很简单,Service Mesh收集服务间通信的Metric指标数据,通过Metric数据可以分析出服务访问当前的各分位耗时,比如99.99分位耗时是50ms,即99.99%的请求都能够在50ms范围内正确返回,我们只需要根据业务实际情况,把要求的分位耗时(如业务要求4个9的成功率,也就是99.99分位)和超时配置进行比较,如果差异过大,则存在超时配置风险。可以定期将当前存在相应风险的配置通过一定的方式知会业务人员,如果业务人员判断确实有问题,就可以尽快对这个风险进行修复。
实际超时配置修复时,可以使用上述分位耗时作为基数,加上一定的偏移作为Buffer,按照之前的经验值,基数较小,可以加上固定时间的偏移(如5~50ms,具体根据实际情况设置),如基数较大时,可以使用固定倍数的偏移(如1.1~1.5倍)。
SLA风险也可以采用同样的思路进行分析,这里不再详细展开。
3.强弱依赖或重试风险
微服务之间通信,如果该链路通信失败会导致整个请求处理失败,一般将这两个微服务之间的关系称之为强依赖,反之称之为弱依赖。我们可以基于服务的强弱依赖关系,进行降级、熔断等处理。
强弱依赖服务风险,是指链路通信之间的关系和预期不符。比如,服务A调用服务B的链路是弱依赖,但随着需求迭代业务逻辑发生变化,可能不经意间服务A调用服务B的链路实际上变成了强依赖,但大家仍然按照之前的先验知识,把它当成弱依赖,这就是一个很大的风险点。特别是链路故障时,基于弱依赖的前提进行降级等操作时,就可能会酿成悲剧,导致整个系统不可用。因此需要有相应的机制,定期检测出当前链路关系的风险点。
强弱依赖风险分析可以采用故障注入的思路,但与直接在线上系统进行故障注入和演练不同,为了不影响线上服务的稳定性,可以通过线下环境进行强弱依赖风险检测。具体思路是采用故障注入配合自动化测试,通过Service Mesh获取到系统的拓扑关系图,自然就可以得到所有的调用链路以及具体的链路关系,这个可以称之为基准链路关系表。针对每个调用链路,通过故障注入的方式让链路调用返回失败,构造一个测试用例,在该测试用例基础上执行正常的自动化测试。如果自动化测试成功,证明该链路失败对整个流程没有影响,说明该链路是强依赖,反之是弱依赖。通过这种方式,可以判断出每个链路最新的链路关系,然后和基准链路关系进行比较,如果有差异,说明链路关系发生了变化,产生了新的链路依赖风险。
重试风险也可以采用同样的思路进行分析,这里不再详细展开。
4.集群或拓扑风险
集群或拓扑风险是风险分析的一个主要来源,之前的工作中遇到过不少集群或拓扑风险的真实案例。比如,某线上集群的一些机器因为保修临时下线一段时间,但机器修复好之后遗漏挂载,导致部分机器白白闲置;服务A调用服务B本来是同机房调用,由于故障或者流量切换演练等原因临时将调用关系切换到调用其他机房的服务B服务,但事后没有切回来,导致服务A调用服务B一直是跨机房访问,影响用户体验和系统稳定性;某服务S线上部署时没有考虑到地理位置因素,将过多的服务节点部署到同一个交换机下,交换机故障时导致服务同时有多个节点不可用,可用节点数不足导致服务雪崩。
集群部署风险或者拓扑风险没有通用的解决思路,需要针对具体的风险增加相应的风险应对措施,以上述列举的服务下的多个节点部署在同一个交换机下为例,一般在同一个交换机下的机器,IP网段信息差不多,可以根据类似的信息,通过程序定期扫描所有的线上集群,根据集群节点的地址信息,判断是否存在拓扑部署风险。
5.链路调用风险
链路实时拓扑数据是一个宝藏,可以从中慢慢挖掘出链路调用层面的很多风险。比如,当前服务调用超过20个下游服务,扇出过大,不太符合微服务的设计准则,可以考虑是否有必要进行进一步的拆分。
微服务架构中,单个请求的链路特别长时,会带来一定的性能问题,因此可以从全局链路拓扑中将TOP10长的链路,或者链路深度超过6的链路列出来,反馈给业务人员,看看是否有必要进行架构层面的调整。
微服务拆分和设计过程中,建议不要出现两个微服务相互依赖的场景,可以通过链路拓扑图查找当前是否存在成环的链路,如果成环,说明服务之间产生了相互依赖,可以将类似风险反馈给业务人员进行整改。
6.链路风险分析的方法论思考
链路风险分析是发现风险并对风险进行抽象和建立自动化检测机制的过程,本质上是对稳定性风险进行精细化管理的系统性工程,需要长期持续地建设下去。
发现风险是链路风险分析的第一步,为了能够持续发现系统新的风险,建议将风险分析和稳定性反模式结合起来:①根据系统中出现的重大故障,以及之前积累的容易出现故障的一些典型问题,梳理出稳定性反模式,也就是稳定性实践中容易犯的,不应该出现的一些模式;②判断这些反模式是否能通过自动化的方式检测出来。
同时为了方便新增风险的检测,可以建立一个完善的风险分析框架,具体包含风险现状、风险改进闭环、风险报告、风险自动通知机制等,新增的风险分析就直接基于框架开发,相当于增加个插件,可以大大提高风险分析的效率。
业务迭代过程中,可能会出现很多临时性的调用关系,调用关系使用一段时间后不再使用,长时间积累下去,可能会导致服务存在不少冗余代码,影响服务的可维护性。我们可以通过实时拓扑图和静态的基准拓扑图进行比较,如果出现基准拓扑图中存在,而实时拓扑不存在的服务调用链路,说明当前链路不再使用,基于实时拓扑和基准拓扑的差异比较,可以考虑将这种冗余调用代码去除。
为了保证变更的质量,服务在新增特性时通常会给它配置相应的特性开关,通过开关来区别不同版本的代码,随着架构的迭代升级,可能会导致不少版本的代码和分支不再使用,我们可以采用和上述冗余链路检测类似的方式。当检测到特性开关判断总是返回特定值时,说明其他分支当前已经不再使用,可以提示相关人员,这类无用代码是否可以移除。
我们也可以从资源调用和使用报表中发现当前服务资源是否有使用不当的地方,比如缓存资源遗漏设置过期时间,缓存资源设置的过期时间过大等;如果存储资源出现过大的对象,或者长期不再使用的数据,也可以反馈给业务方相关人员,以确定使用上是否需要进行调整。