系统成功率99.99%+,美团CI/CD流水线引擎演进实践( 五 )


解决方案:增加pending的状态表示作业已被决策到 , 并通过数据库乐观锁机制进行状态变更 , 保证仅有一个决策会真正生效 。 状态变更过程异常:由于存在异构数据库 , 状态变更和加入队列可能存在数据不一致 , 导致作业无法被正常调度 。
解决方案:采用最终一致性的方案 , 允许调度的短暂延迟 。 采用先变更数据库 , 再加入队列的操作顺序 。 利用补偿机制 , 定时监测队列队首的作业信息 , 若pending状态下的作业有早于队首作业的 , 进行重新入队操作 。
②作业拉取过程:任务中心根据Worker拉取作业的事件请求 , 从等待队列中获取待调度作业 , 将作业的状态从pending变更为scheduled , 并返回给Worker 。
系统成功率99.99%+,美团CI/CD流水线引擎演进实践
文章图片
图6状态机-ACK作业丢失问题:这里存在两种情况 , ①作业从队列中移除 , 但在状态将要变更时异常了;②作业从队列中移除 , 也正确变更了状态 。 但由于poll请求连接超时 , 未正常返回给Worker 。
解决方案:前者通过作业决策环节中对pending状态的作业补偿机制 , 重新加入队列;后者对于状态已变更的情况 , 已调度的作业增加ACK机制 , 若超时未确认 , 状态会流转回pending状态 , 等待被重新拉取 。 作业被多个Worker拉取:Worker在接收到作业后 , 遇到长时间的GC , 导致状态流转回pending状态 , 在Worker恢复后 , 可能出现作业已分配到另一个Worker上 。
解决方案:通过数据库乐观锁机制保证仅有一个Worker更新成功 , 并记录作业与Worker的关系 , 便于对作业进行中止以及Worker故障后的恢复操作 。
3)决策过程
决策过程是从所有未启动的作业中筛选出可以被调度的作业 , 通过一定的顺序将其提交给任务中心 , 等待被资源拉取的过程 。 整个筛选过程可以分为串并行顺序、条件过滤、优先级设置三部分 。
系统成功率99.99%+,美团CI/CD流水线引擎演进实践
文章图片
图7决策过程串并行顺序:相对于DAG中复杂的寻路场景 , 流水线场景比较明确 , 是将代码逐步加工验证 , 通过开发、测试、集成、上线等一系列阶段的过程 。 阶段间是严格串行的 , 阶段内出于执行效率的考虑 , 会存在串并行执行的情况 。 这里通过模型设计 , 将DAG的调度问题转变成作业的先后次序问题 , 引入runorder概念 , 为每个组件作业设置具体的执行次序 , 根据当前已执行作业的次序 , 快速筛选出下一批次序仅大于当前的作业 , 若并行执行 , 仅需将作业的次序设置成相同即可 。
系统成功率99.99%+,美团CI/CD流水线引擎演进实践
文章图片
图8串并行决策条件过滤:随着业务场景扩展 , 不是所有的作业都需要调度资源 , 进行真正的执行 。 如某类耗时的组件 , 在代码和组件参数都不变的情况下 , 可以直接复用上一次的执行结果 , 或者在系统层面针对某类工具异常时进行组件跳过的降级操作 。 针对这类情况 , 在作业真正提交给任务中心之前 , 会增加一层条件判断(条件分为全局设置的系统条件以及用户条件) , 这些条件以责任链形式进行依次匹配过滤 , 根据匹配到的条件单独向任务中心提交决策 。 优先级设置:从系统全局考虑 , 在作业出现积压时 , 业务更关心核心场景下整条流水线是否能尽早执行完成 , 而不是单个作业的排队情况 。 所以 , 在优先级设置上除了基于时间戳的相对公平策略外 , 引入流水线类型的权重值(如发布流水线>自测流水线;人工触发>定时执行) , 保证核心场景流水线相关作业能够尽早被调度到 。