【日常随笔】业务变更风险观测的技术架构设计

32 阅读12分钟

本文主要内容搬运自笔者以下CSDN博文,欢迎各位老铁同步关注笔者CSDN博客!

在线上服务变更过程中,我们希望可以通过一套实时观测机制去监测业务线上服务的风险,从而能够确保线上稳定性,在出问题时可以及时回滚变更。今天这篇文章,就简单讲一下业务变更风险观测基础的技术架构需要怎么设计。主要讲3套设计:变更观测的任务流程、观测任务的管理调度,以及检测能力的精细化调度。

变更观测的任务流程

首先我们聚焦于建模变更观测的过程。变更观测的生命周期,一般来讲,当服务某阶段变更开始后,观测会开始,然后当服务某阶段变更完,一般还需要停留观察一段时间,确定线上没有遗留风险之后,观测才会结束。可以简单的认为,一次变更观测,关联一次发布的某一个过程。所以一个观测任务,结构数据上需要包含发布工单的元信息、观测参数的元信息,以及任务自己的运转状态,同时每个任务实例需要被有序的调度起来,因此所以要有一个调度系统去处理每个任务实例的状态推进。

然后,再细一个粒度,对于一个特定的变更风险点,我们也需要用一个特定的观测能力去cover,所以对于每个观测能力,也要和上层的观测任务一样,有自己的元信息和状态转换定义。任务对能力是一对多的关系,一个观测任务当中,可以通过某种编排,把不同能力在不同的时间点启动起来,切入到发布过程的不同时机,这样就能够形成灵活的变更观测。

从这些角度出发,以一个简单的串行思维,整个变更观测任务需要做以下的动作:

  • 任务创建
    • 预处理任务启动参数,确定需要观测的服务对象
    • 获取观测策略,确定需要启动的监测能力
    • 落库一条任务记录,调整为init状态,缓存观测能力和服务对象等上下文信息
    • 返回任务记录,任务创建完成
  • 任务推进
    • 确认任务是否在终止态,如果没有终止就继续推进
    • 确认任务是否需要提前终止(比如变更取消的情况)
    • 确认当下需要新启动哪些检测项,如果有需要做异步启动,关联这个任务
    • 确认已启动的检测项最新的状态和结果是什么,做状态推进动作
    • 对当下的结果做动态降噪,如果有必要则实时旁路告警,缓存最终决策的结果
    • 确认是否所有检测项达到终止态,达到则终止任务,做执行结果和告警的最终落库

当然,其中每个点还可以详细挖掘,首先是观测策略怎么去匹配。策略的匹配,涉及到每个变更渠道会通过什么样的方式去管理资源,有些渠道可能具备业务性质,通过树结构去管理每个业务下面的资源,有些则可能是简单的uuid的形式。

这里,如果渠道是通过树结构管理资源的话,那么需要考虑一条root到leaf的路径上,对应的观测策略要取哪些,是取leaf就近的一个,还是说所有都取,或者是其它怎么样的逻辑。从笔者的经验来讲,一个比较合适的方式是,所有都取,但每个策略需要排优先级,按照优先级去去除同质的检测项。这样通过组合代替继承的方式,可以兼容渠道各种管理资源的方式,也可以满足更多的业务需求。

然后是不同的观测能力怎么去做联动。好比说,对于某一个风险点,我们需要把变更上下文分析、数据告警监测、结果降噪、风险周知以及根因分析这些能力给串联起来,对于其它风险点又可能有不同的能力联动和切入条件,那么整个任务的逻辑编排将会是非常复杂的,简单的一个实现思路是通过一条主线链路加上多条支线链路去兼容的方式,但这也并非最完美的描述。

从一个产品化的角度讲,变更观测从行为上看,其实可以用一个行为树来描述,也就是说观测的每一刻,我都需要动态地判断哪个检测能力要启动,哪个能力要停止,哪个能力的上游依赖完成了可以运行,然后启动的话传入什么参数,不同时间点传的参数也会不一样,以及线上如果有其它的变更事件,需要对任务怎样动态调整。对于用户而言,可以通过可视化的方式去编排整个行为树,这样就可以让用户非常方便地去定制化编排整个观测任务。

最后就是决策结果怎么和发布工单联动。从变更质量管理的角度来讲,我们通常希望变更观测出现风险时,对变更渠道的发布过程进行卡点或者其他流程干预操作。要实现这个事情,更多的考虑还是变更观测方和变更渠道方在合作模式上怎么达成共识。一般来讲合适的方式是,渠道本身发现任务结果fail然后去卡流程,但风险确认跳过的操作统一注册给变更观测方,在跳过时变更观测报告调整为skip状态并且skip掉渠道的卡点。这样一来不会有过多侵入的操作,二来也能够达到变更管控的效果。

观测任务的管理调度

对于变更风险观测来说,任务执行是最核心的部分,但从更宏观的角度来讲,一个变更观测平台,需要对大量的观测任务做统一调度,这样才能把整个观测平台给支撑起来。要解决这个大问题,可以拆分几个子问题去解决:多任务并发需要如何处理,任务调度的消息协议需要如何设计,如何保证整个调度系统的稳定性。

首先第一个问题是,多任务并发的整个系统设计。主要是两个路子,一种方式是有一个任务驱动服务去不断地向一个MQ去生产和消费任务调度信息,好比说创建任务的过程,HTTP接口逻辑先让任务记录落库,然后produce一条任务执行的消息,之后consumer消费了任务执行消息后,就initialize整个观测任务,开始执行,执行过程中不断生产消费poll的消息,如果用RMQ的话也可以借助延迟队列机制去定时推进任务进程,直到任务结束。另外一种方式是通过一个外部的cronjob去查询近期的非终止态任务,然后一个个去推进执行,不走消息队列。

两种方式各有利弊,后者因为有定时的查询过程,对DB的压力会稍微大一些,因此如果任务量非常多的话,查询时延会比较高,导致任务推进缓慢,而前者主要依赖MQ的稳定性,如果消费逻辑不稳定,容易造成消息积压或者任务推进过程中断。整体来看前者的架构会更加灵活一些,用mq分担一些任务推进工作,在这个基础上,再去附加一个外部的cronjob做兜底。对于MQ的生产消费,如果任务量有预估,可以用定容的服务去处理produce/consume逻辑,当然如果有计费要求,用faas会更加合理。

第二块是消息协议设计。这块会主要关注创建任务需要包括哪些信息,可以大致做这样的分门别类:

  • 任务创建的元信息:哪个job、创建人、创建来源以及任务的调度参数
  • 工单(阶段)的上下文信息:工单所属渠道、工单ID、变更类型、阶段唯一key以及放量比例等信息
  • DevOps的上下文信息:需求/发布信息、流水线ID等信息
  • 风险观测参数:上下游服务、观测时长、通知webhook等信息

这样,一个观测任务就能够精准对应到一次发布、一次特定节点以及一组特定的执行策略,就能够确定整个任务的运行方式和观测内容。

第三个问题是稳定性保障。除了一些必要的中间件/服务监控告警之外,影响整个系统稳定性的,还是producer/consumer和mq这个搭配。这里有几个点需要考虑的:

  • 代码:producer/consumer的panic需要recover+ack,防止任务进程中断;channel/singleflight/waitgroup阻塞之类问题需要有重试机制、死信队列兜底,先保证进度信息不丢失再做修复。
  • 容量:观测任务的处理延时主要在任务推进,一次任务推进的时间可能很长,兜底需要1~2min的timeout,所以除了对服务有一个合理的定容之外,整个任务推进的逻辑当中,需要把能够开goroutine异步执行的步骤尽可能单独拿出来,优先保证消费延时不要太高。如果遇到一个观测项又有多个子任务需要调度的场景,一个好的方法是把多个子任务调度放到单独的服务中进行,这样不影响主流程;如果实在消费不过来了,也可以通过一些兜底机制,根据任务执行时间或任务重要性,自主适配延长下次consume的间隔,从而减轻自己压力。

总体来看变更风险观测的任务调度,大体设计思路方面不需要做的非常复杂,重要还是去有一套稳定性兜底机制,保证整个生产消费链路能够持续稳定运转。

检测能力的精细化调度

在实际业务场合,变更观测检测项的执行方式,一定有很多业务定制化的部分。如果一套任务执行逻辑适配10个业务的各种需求,让不同检测能力适配不同场景,在不同的变更时机运行,那么配套也得需要一个比较通用简便的技术实现方式,让适配业务定制化变更观测需求变得更加容易。为此,结合实战经验,笔者推荐通过事件描述检测任务执行状态,对检测能力做精细化调度,是一个可行的技术方案。

首先是为什么解决这个问题通过事件驱动比较合适,主要有两个原因,一是实现成本比较低,另一块是能尽可能cover更多的业务场景。首先是实现成本方面,单个任务的所有中间事件都可以放到基于redis的事件总线当中,如果redis的缓存量和吞吐量足够大的话,只需要对每个任务的事件context做逻辑隔离,就可以满足需求。在笔者的实战场景下,任务调度模块只有一两个人做持续维护,那么这种实现方式就是非常合适的。

然后是业务场景的cover。对于单个变更观测任务,或者广义讲变更观测关联的测试类、监控类以及告警降噪类任务,都可以通过一套基于事件调度的系统做控制。简单来说,单个观测能力执行配置,需要指定启动和终止的条件,而启动终止条件内在可以通过事件KV来表达。比如,对于告警监听类能力,我们期望在变更滚动到50%时启动,变更结束+管控观察时长之后停止,那么我们可以先开发一个内置的变更进度监控能力,变更进度监控能力在变更观测任务开始时启动,产出变更进度相关事件,当某一次任务推进发现变更滚动到50%之后,就可以启动这个告警监听能力。结束也是一样,有了变更进度监控,我们可以得到变更完成时间以及目前距离变更完成的停留时长,从而在合适的时机结束掉告警监听类能力。对于其它能力也是一样,通过不断产出事件,我们可以堆积出当前变更观测进度状态,通过持续轮询推进,就能够让每个能力在合适时机启停。

总的来讲,通过事件驱动和标准化策略配置,变更风险任务调度能够灵活支持各种起止条件,提升变更过程的自动化和可控性。这不仅提高了检测任务的执行效率,也为系统安全和稳定性提供了有力保障。