本文提到的异常检测(Anomaly Detection)特指在运维领域中对时序数据的异常检测,目的是为了发现时序数据中状态的变化。
在我们看来,异常检测一般可分为两类:简单异常检测和复杂异常检测
简单异常检测:一般指恒定阈值检测,比如判断可用性指标是否小于 99.99%,如果小于则检测结果为异常,否则检测结果为正常。简单恒定阈值检测一般适用于可用性、资源利用率等监控指标。
复杂异常检测:对于收入、错误率、流量等业务监控指标,需要检测天/周/月/年等环比变化或者突增突降等状态变化,这类业务监控指标的维度特征较多(比如地域、运营商等),特征变化也比较快(例如电商定期搞活动,流量瞬间涨起来,干扰正常的异常检测)。恒定阈值检测往往无法检测到这类业务监控指标的状态变更,所以还需要复杂异常检测算法来检测业务监控指标的异常。为了发现监控指标的状态变化,复杂异常检测往往会采用机器学习、深度学习等比较复杂的技术。
和简单异常检测相比,复杂异常检测对落地流程和异常检测的运行平台提出了更高的要求。
落地复杂异常检测的阻塞点
为了支持简单异常检测,异常检测的运行平台只需要能够支持用户添加自定义报警判断规则即可。比如,对于上面提到的可用性指标,用户可以在系统中将报警判断规则配置为表达式“SLI < 99.99%”,然后等着接收报警就可以了。
然而对高级异常检测算法,算法从研发到上线,一般需要包括以下三步:
1.线下编写算法脚本(一般是 Matlab 或 Python 脚本),并根据历史数据,离线训练算法所依赖的参数,通过用历史 Case 进行回溯验证效果。在这个过程中,算法工程师需要反复调整算法参数,直到准确率和召回率都达到目标为止。
2.将算法脚本改写成线上代码(一般是 C++、JAVA 语言等编译型语言)。这是因为线下编写的算法代码一般和线上运行代码使用不同语言开发,线下实验算法代码更侧重研发效率,需要快速迭代和测试,而线上运行代码更侧重运行效率,高效稳定运行。
3.最后将改写后的算法代码生效到线上,并观察其运行稳定性和资源消耗情况,及时调整线上资源分配情况。
以上流程在实践的过程中存在若干阻塞点,导致复杂算法落地时间长,算法迭代效率低:
1.线下实验的过程中,历史数据、历史 Case、不同实验所使用的算法、参数和效果全靠人工管理,常常出现指标数据不全,历史 Case 不全,实验过程兜圈子的情况。
2.线下代码和线上代码开发语言不一样,代码移植需要消耗比较多的时间,常常不能保证线上代码和线下代码的效果完全一致。
3.一些复杂算法对资源的消耗很大,贸然上线会影响监控系统部分或整体的稳定性。
落地复杂异常检测的需求
上述阻塞点很容易导致算法迭代速度跟不上指标变化速度的情况,最终限制了检测效果的提升。所以,为了保证算法的顺利落地,我们需要提供一个新的异常检测支持方案,满足以下的需求:
1.需要一个方便算法快速迭代和算法验证的环境,用于在线下调试算法脚本,并对历史 Case 回溯,保证算法的普适性。
2.需要能弥合线下脚本和线上代码鸿沟的机制,尽快将算法生效到线上,能快速验证算法代码的真实效果,否则线下实验脚本和线上生效代码迁移成本太高,费事费力费程序员。
3.需要评估线上代码的资源消耗和稳定性情况。因为复杂异常判断算法,其资源需求差异性特别大,比如有的会采用深度学习等非常耗 CPU/GPU 的算法,而有的仅仅是简单公式计算。另外,这类算法开发迭代特别快,算法代码很容易引入 Bug,所以需要在不影响其他线上算法运行的同时,采用线上真实流量验证算法稳定性。
4.需要分离算法代码和算法参数,并支持算法参数的独立更新。因为算法经过快速迭代后,会逐渐稳定下来,但是算法的参数是对历史数据的特征表达,所以算法所依赖的参数需要周期性更新,保障算法达到最优效果。
落地方案
为了解决上述问题和需求,我们推出了异常检测运行平台。基于运行平台,算法工程师可以用脚本语言(当前支持 Python 脚本语言)线下编写异常检测算法,并在线下回溯历史 Case,当策略调试完毕后,可以直接将 Python 算法脚本生效到到线上。同时,还支持算法参数的独立更新,大大加快算法的生效速度。
异常检测运行平台包括三个环境:离线环境、在线环境、近线环境,下面详细介绍。
1 离线环境
离线环境会提供如图 1 所示的策略开发框架,异常开发框架提供了 Python 运行环境和常用的 Python 库,基于开发框架,算法工程师采用一致的抽象接口编写算法代码,这样可以保证在线下开发的算法代码可以直接放到线上环境运行,从而弥合线下脚本和线上代码鸿沟。为了回溯 Case,开发框架还提供了历史时序数据组件、异常判断评价组件(支持准确率、召回率、F1 Score 等评价指标)。由于复杂异常检测算法不像恒定阈值算法可以根据数据直观看出判断结果,复杂异常检测算法往往需要运行并输出异常判断结果(能图形化展示更好),才能评估算法效果,所以开发框架提供了图形组件,可以图形化展示异常检测结果。
图 1 策略开发框架
图 2 展示了算法开发接口,其中包括四个标准接口:
load_model 函数负责加载算法参数;
get_data 函数负责加载指定时间段的历史时序数据;
initialize 函数负责在算法正式运行前进行初始化,比如加载算法参数、申请内存等等;
detect 函数负责对时序数据点进行异常检测,并返回异常检测结果(正常或异常)。
图 2 用于高级异常检测的抽象接口
2 在线环境
算法工程师在线下环境基于开发框架开发完策略算法后,可以将算法发布到在线环境。在线环境提供了跟策略开发框架一致接口的策略运行时环境。策略运行时环境会接收上游发送的时序数据,并驱动 Python 算法脚本周期性运行,同时将产生的异常判断结果发送到下游,用于报警通告。
图 3 在线环境架构
在线环境的架构图如图 3 所示,在线环境主要包括以下三个模块:
任务分发模块:负责管理运维人员提交的高级异常检测算法配置,并将每个算法配置组装成任务,分配给任务运行模块。
数据调度模块:数据调度模块周期性从任务管理模块同步任务的分配信息,根据任务分配信息,将每个任务所需的数据调度给相应的任务运行模块,同时将数据也 Copy 一份,写入到时序数据缓存中。
任务运行模块:任务运行模块周期性从任务分发模块拉取分配到的任务,并为每个任务启动一个策略运行时环境。策略运行时环境支持跟开发框架相同的接口,所以可以直接驱动基于开发框架开发的算法代码的运行。策略运行环境刚启动的时候,会调用 intialize 函数,进行初始化操作,然后策略运行环境不断接收数据调度模块调度过来的数据,并驱动调用 detect 函数,detect 函数会对接收到的数据进行判断,并返回判断结果(正常或异常),运行时环境收到判断结果后,将其发送到下游,用于报警发送。有时算法在刚启动或运行的时候,需要拉取近期的时序数据,这时通过 get_data 函数从时序数据缓存中获取即可。另外,任务运行时环境还会周期性检测算法依赖的参数是否有变更,如果算法参数被更新了,则会调用 load_model 函数重新加载配置。
3 近线环境
在线下环境编写算法代码,如果直接贸然上线到在线环境,往往会存在很多问题,所以策略算法在离线环境验证可用后,首先会放到近线环境运行起来,近线环境和线上环境的架构和功能其实没有本质差别,只是用途不同而已。近线环境的目的,一方面是为了用线上真实流量数据来验证算法的资源消耗,以发现算法运行的真实资源需求,只是不真正发送告警而已;另一方面,是为了验证算法的稳定性,比如是否有内存泄漏、是否有崩掉、是否有错误日志等等。如果发现有问题,算法工程师可以快速调整并重新部署到近线环境进行验证。
总结
本文主要介绍了异常检测的相关背景、应用场景和需求分析,然后我们给出了百度云的高级异常检测算法快速落地方案——异常检测运行平台。目前运行在这套异常检测运行平台上的高级算法超过 20 个,每天处理近千万监控指标的异常判断。算法的线上迭代周期从周级别减少到天或小时级别,很好地支撑了业务方对不同高级异常检测的需求。另外,我们还将平台开放给业务运维人员使用,由业务运维人员研发的异常检测算法可以有效引入业务线人员的专家经验。
作者介绍:
周伟,百度云高级研发工程师,负责百度云智能运维(Noah)告警通告系统的设计和研发,在大规模分布式系统、运维监控、精准报警等方面具有广泛的实践经验。
本文转载自公众号 AIOps 智能运维(ID:AI_Ops)。
原文链接:
https://mp.weixin.qq.com/s/fugbnXw1l_AjJB8Dj2xeUg
评论