整体架构
- 基线 管理模块:负责基线创建、更新、删除等操作,管理基线元信息,包括保障任务,承诺时间,余量及报警配置等);
- 基线 实例生成:系统每天定时触发生成基线实例,生成实例的同时根据保障任务,由下而上逐层遍历 (BFS)所有上游任务并生成基线监控埋点。生成基线监控埋点的过程中,会计算每个任务节点的预测运行时长,承诺时间,预警时间,预警最晚开始时间,承诺最晚开始时间。此外,系统会给基线监控任务添加基线出错/变慢报警规则,当任务执行触发规则后,通过基础报警服务发送基线报警事件;
- 监控 埋点 校验:系统维护一个延迟队列,根据校验时间点(预警最晚开始时间,承诺最晚开始时间以及破线加剧时间校验点),定时触发监控埋点校验任务实例运行状态,如果在时间点实例未运行成功,产生基线预警/破线报警事件,发送给基础报警服务发送报警。
由于基线实例生成和基线埋点检测是基线监控的核心模块,因此本文只着重介绍下这两个模块。
基线实例生成
- 每天固定时间点(如22:00),根据基线类型及业务日期生成对应的基线实例。
- 针对每一个
基线实例
,系统根据该基线实例对应的监控链路(任务DAG),由保障任务为起点,自下而上逐层( BFS ) 计算各任务对应的监控埋点实例的校验时间节点,包括预测运行时长
、预警时间
、承诺时间
、预警最晚开始时间,承诺最晚开始时间。
如上图所示,上游任务(B)的预警时间为其子任务实例埋点的预警最晚开始时间,
任务节点中的数字表示任务的预测运行时长,如节点A(1.5h),表示A的预测运行时长是1.5小时。
如上图所示,基线保障任务为A,承诺时间为9:00,用户设置的预警余量为0.5h,结合系统推算出该任务本次的预测运行时长为1.5h。因此,任务A监控埋点的预警时间为8:30(9:00-0.5h),预警最晚开始时间为7:00(8:30-1.5h),承诺最晚开始时间为7:30(7:00+0.5h)。
上下游任务之间监控埋点的各时间节点方法如上图所示,满足:上游任务的承诺(预警)时间 = 下游任务的承诺(预警)最晚开始时间。
上图示例只是理想情况,但实际上任务链路会非常复杂,如跨层依赖、循环依赖非常常见。此外,任务链路也是有可能动态变化的,上游依赖新增或者减少也是个普遍现象。因此,基线实例生成时,需要针对上述情况进行处理,以保证基线监控的有效性和合理性。下面,我们针对每种场景介绍基线监控算法的解决办法。
-
基线监控的任务链路变化了怎么办?
目前,基线监控算法是通过基线实例生成时刻该基线监控的任务链路“快照”来生成监控埋点实例的,暂未针对监控埋点生成结束后,基线覆盖的任务链路发生变化的情况进行处理。即,用户操作任务并不改变已经生成的基线监控埋点实例的信息(计算得来的各种时间及任务与基线的映射关系等),而是等到下一次生成基线实例的时候重新去计算。具体实现时,系统会将任务DAG进行缓存(1h),以提高埋点实例生成的效率。
-
基线覆盖的任务链路存在跨层依赖怎么办?
由于在计算监控埋点实例的时候是由下至上逐层计算的,可以理解为是个局部计算,无法获取整个任务链路的全貌。因此,如果基线覆盖的任务链路中存在跨层依赖,那么同一业务任务实例上的监控埋点的时间点需要不断更新至最早值。如下图所示,任务A依赖任务C和E,任务C依赖于任务E,而任务A又直接依赖于任务E。保障任务A的埋点实例计算结束之后,可以计算任务B、C、D、E的埋点实例信息;而当计算任务C的埋点实例信息时,任务E的埋点实例需要根据任务C的埋点实例信息进行更新。这样才能保证整个任务链路监控的合理性。
-
基线覆盖的任务链路存在循环依赖怎么办?
基线覆盖的任务链路中存在循环依赖,一般是由于某两个任务之间在业务时间存在offset导致的。如下图所示,比如任务B 业务时间23:00的实例依赖任务C 业务时间23:00的实例,而任务C 业务时间23:00的实例又依赖于任务A 业务时间22:00的实例。
对于这种情况,处理原则为:只保留任务最新业务时间(latest_task_time
)对应的埋点实例,早于latest_task_time
的业务时间对应的埋点实例直接丢弃。这是考虑到对更早时间点的实例进行监控的意义不大,因为前一天的基线监控已经发现出问题并触发告警了。
基线埋点校验
基线实例生成结束后,将生成的监控埋点实例维护到一个延迟队列BaselineTimeQueue
里,Delay时间节点、监控埋点实例校验阶段及对应阶段触发的报警类型三者之间的关系如下图所示:
-
基线监控埋点实例的初始阶段为基线预警校验阶段(
CHECK_START_WARNING_TIME
) , 其Delay时间点为预警最晚开始时间(earliest_start_time_for_warning
)。当到达earliest_start_time_for_warning
时间节点时,监控埋点对应的任务仍未开始运行,且该任务是该基线监控链路上的首个满足条件的任务,则基线实例的状态由安全更新为基线预警,并发送基线预警报警 。 无论是否触发报警,监控埋点实例的状态都会从CHECK_START_WARNING_TIME
流转至基线 破线 校验阶段(CHECK_START_COMMIT_TIME
),并且重新放至延迟队列中,等待基线破线的校验。 -
当到达承诺最晚开始时间(
earliest_start_time_for_commit
)时间节点时,监控埋点对应的任务仍未开始执行,且该任务是该基线监控链路上的首个满足条件的任务,则基线实例的状态由安全/基线预警更新为基线 破线,并发送基线破线报警。 -
在基线破线校验结束之后,需要判断是否需要进入基线破线加剧校验阶段:
- 如果当前任务或其上游存在破线任务,且当前任务已经开始执行,则基线实例状态更新为基线破线加剧检查阶段(
CHECK_OVERTIME_INTENSIFY
),Delay时间为基线破线加剧校验时间节点(overtime_intensify_time
),即任务实际开始时间 + (预测运行耗时 * (1 + N%)); - 如果当前任务尚未开始执行,则基线实例状态更新为等待基线 破线 加剧检查阶段(
CHECK_WAIT_OVERTIME_INTENSIFY
),此时Delay时间为等待基线破线校验时间节点(wait_overtime_intensify_time
),即破线开始时间 + (预测运行耗时 * (1 + N%))。
- 如果当前任务或其上游存在破线任务,且当前任务已经开始执行,则基线实例状态更新为基线破线加剧检查阶段(
-
当到达
wait_overtime_intensify_time
时间节点进行校验时,若任务仍未开始执行,则检查阶段保持不变,wait_overtime_intensify_time
增加 30 秒,重新入队等待下次检查。 -
当到达
overtime_intensify_time
时间节点进行校验时,若任务仍未运行成功,则触发基线 破线 加剧报警,并将基线实例的状态更新为FINISH_WITH_UNSAFE
,埋点监控结束;若任务已运行成功,则不触发报警,并将基线实例的状态更新为FINISH_WITH_SAFE
,监控结束。
未来,我们将继续针对基线监控进行优化,如基线关键路径分析、基线实例生成效率优化等,不断提高基线监控算法性能,完善基线链路分析能力,不断提升用户体验,致力于向火山引擎DataLeap用户提供更强大的全链路监控运维能力。