零碎实现
整体架构
- 基线治理模块:负责基线创立、更新、删除等操作,治理基线元信息,包含保障工作,承诺工夫,余量及报警配置等);
- 基线实例生成:零碎每天定时触发生成基线实例,生成实例的同时依据保障工作,由下而上逐层遍历 (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用户提供更弱小的全链路监控运维能力。