该分享是阿里妈妈Goldeneye业务监控平台的智能监控解决方案。
这个分享主要包括智能监控的技术实现,以及大规模日志监测数据的自动化接入两部分。我先介绍一下智能监控部分,下一期分享中我的两位同事将给大家着重介绍日志分析处理的计算。智能监控现在其他一些公司也有在做,希望通过这次分享能够给大家带来一些新的启发,也欢迎大家能够提出问题和建议,互相切磋交流经验。——马小鹏
分享内容的提纲如下:Goldeneye智能监控的业务背景、技术思想、技术实现细节、难点和今后的优化方向。
马小鹏,阿里妈妈全景业务监控平台技术负责人。2013 起在阿里从事大规模系统日志分析及应用的研发,曾经主导了直通车广告主报表平台和实时报表存储选型。在加入阿里之前,曾负责网易电商 App 数据统计平台的研发。
Goldeneye作为阿里妈妈业务监控平台,主要在业务日志、数据的实时统计分析基础上做监控报警以及辅助定位。阿里集团内部也有很多的监控平台,它们在开放性上做的很好,接入成本也不高,但是监控阈值也是开放给用户自己设定。这种情况下,对于业务监控人工维护阈值就比较复杂,需要有丰富的经验来拍定阈值,需要人工持续的维护不同监控项的监控阈值。所以,在业务快速发展的前提下,传统的静态阈值监控很容易出现了误报、漏报的问题,而且人工维护成本高,监控视野局限。Goldeneye就是在这种基础上,我们试着从大数据应用的角度,去解决业务监控中的问题,由此诞生的。
(1)体量大:Goldeneye现在接入的业务线覆盖了阿里妈妈主体的90%业务,每天处理的日志量在100T以上,业务监控需要对各业务线的流量分层级实时监控,数据以1分钟为周期,一般监测数据以5分钟或1小时为周期,监控目标非常多,按人工维护这些监控的阈值、启停、生效实效等几乎是达不到的。
(2)变化多:业务监控的监测数据大都是业务指标,不同于系统运维指标,比如RT/QPS/TPS等一般是比较稳定的,业务指标具有周期性变化的特点,比如工作日和节假日的区别、业务营销策略调整的影响等,在这种情况下人工设定的静态报警阈值准确性就很难保障了。
(3)迭代快:随着阿里妈妈资源整合和业务的快速发展,监控目标也经常发生变化,比如流量监控资源位的调整、效果监控的产品类型划分等,曾经出现过新流量上线后的监控盲点。
图1 Goldeneye技术背景
通常的业务监控系统或平台,都是由采集、数据处理、检测、报警等模块组成的,Goldeneye也是如此,不过它的技术架构上用了阿里内部的一些技术中间件,比如采集我们使用TimeTunnel(它有agent在各台日志服务器上拉日志到Topic,并且负责将离线日志放到ODPS上),这部分我不再介绍了。
数据处理我们使用的jstorm和ODPS MR job分别对日志进行实时、离线批处理,主要包括日志解析、校验、时间周期归一化、聚合、写存储(HBase)等操作,这部分下一期分享中我的同事会详细介绍。今天的分享主要集中在阈值预测、监控检测、报警生成&通知、辅助定位这四部分。
智能监控就是让系统在业务监控的某些环节上代替人工执行和判断的过程。人工维护监控目标和阈值是以经验为参考的,系统如何自动判断哪些目标需要监控、自动设定监控目标的阈值水位、不用人力维护,是基于对历史样本数据统计分析得出判断依据。
通过收集监测数据的样本,并使用智能检测算法模型,让程序自动对监控项指标的基准值、阈值做预测,在检测判断异常报警时使用规则组合和均值漂移算法,能地判断需要报警的异常点和变点。
以往我们添加监控有两种做法:
给指标M1设置一个水位线,低于(或高于)水位,触发报警;
给指标M1设置同比、环比波动幅度,比如同比波动20%、环比波动10%触发报警;
以上两种方式,是平常大家常用的监控方式,但是效果确不理想,这种静态阈值长期来看没有适应变化的能力,需要人工维护,而且报警准确性也依赖于同环比数据的稳定性。
我们能否让系统具备自动适应变化的能力,自动调整阈值水位?就如同手动挡的汽车换成自动挡一样,可以根据速度自己调节档位。
当我们的监控系统具备预测动态阈值的能力后,监控项的维护是否也可以交给系统去做?
可能大家也曾遇到过类似的情况,旧的监控项已经没有数据了,新的监控目标却因为各种原因被漏掉,人工维护监控项需要及时同步上下线变更,但是当我们需要监控的目标有一千个、一万个甚至更多的时候,人力是无法一直跟进这些监控项的维护工作的,或者说这种工作比较单调容易被忽视。
我们能否将判断如何筛选监控项的规则交给系统,让它去定期检查哪些监控项已经实效,哪些监控项需要新增,哪些监控项的阈值需要调节。这种发现规则是稳定的,仅仅是依据发现规则得出的监控项内容在不断变化而已。
当我们的监控系统具备预测动态阈值、自动发现并维护监控项的能力后,如何达到不漏报和不误报之间的平衡?
对于监控而言,漏报是不可容忍的,但是误报过多也容易使人麻木。
通常的做法是为了不被误报干扰至麻木,会把阈值调节得宽松些,但是这种做法容易产生漏报,尤其是下跌不太明显的情况。
Goldeneye采取的思路是对误报case欲擒故纵,在首先确保不漏报的基础上降低误报率。先监控产生疑似异常点,这一环节我们基于动态阈值去检测时相对严格一些(或者说这一环节不用考虑报警收敛的问题),然后对这些疑似异常点再做验证、过滤,终生成报警通知,验证和过滤的依据是预先定义的规则,比如指标组合判断、报警收敛表达式等。
下面介绍技术实现的一些细节,分为监控系统的架构、动态阈值、变点检测、智能全景、辅助定位五个点。
Goldeneye监控系统的四个输入:实时监测数据、历史数据、预测策略、报警过滤规则。
其中,历史数据是实时监测数据的积累。
而预测策略主要包括:
(1)阈值参数:设置基于预测基准值的系数决定阈值上下限区间、分时段阈值预测系数、分报警灵敏度阈值预测系数;
(2)预测参数:样本数量、异常样本过滤的高斯函数水位或者过滤比例、基于均值漂移模型的样本分段选取置信度等。
关于报警过滤规则,主要是为了在充分捕捉疑似异常点的前提下,过滤不必要的报警。比如指标M1异常,但是组合规则是M1和M2同时异常才报警,这种就会过滤掉。再比如,按照报警收敛规则,一个监控项的第1次,第2次,第10次,第50次连续报警值得关注,可以设置收敛表达式为1,2,10,50,那么在报警通知生成时对于第3,4,…,9,11,12,…,49次报警可以忽略,因为反复通知的意义不大,这个规则可以按需要达到自动收敛。也可以在同一监控项的多个实例同时发生异常报警的情况下,按规则合并成一条报警,这些规则可以按具体情况去实现,终的目的是以简洁的方式暴露值得关注的报警。
(这里补充一句,我们近在考虑新的收敛方式,对第1条和1条报警,并且自动计算出累积gap,这样异常的起止和影响范围更明显)
图2 Goldeneye报警系统架构
监控使用控制图,对监测指标的时间序列可视化,让人们可以清楚的看到指标的波动。基于控制图的监控,以往很多都是静态阈值方式,比如前面提到的静态水位线、同环比。动态阈值是为控制图的时间序列每个点,预估该点对应时刻这个指标的基准值、阈值上限、阈值下限,从而让程序可以自动判断是否有异常。因为这种预估基于过去几个月甚至更多的历史样本作为参考,所以比同环比两个数据作为参照的准确度要高。动态阈值预测的理论基础是高斯分布和均值漂移模型。
图3 动态阈值原理
动态阈值预测的步骤主要是这样:
(1)样本选取:这个根据自己的需要,一般建议选取过去50天左右的样本。
(2)异常样本筛除:这个过程主要使用高斯分布函数过滤掉函数值小于0.01,或者标准方差大于1的样本。
(3)样本截取:因为后来我们优化的版本,在(2)的基础上使用均值漂移模型对历史样本在时间序列上进行分段检验,如果有周期性变化、或者持续单调变化,则会反复迭代均值漂移模型寻找均值漂移点,然后截取离当前日期近段(或者可以理解为近一段时间平稳的样本序列)。样本选取还有一个需要注意的问题,节假日和工作日的样本要分开选取,预测工作日的阈值要选择工作日的样本,节假日亦然,也就是对预测样本从日期、周末、平稳性三个维度拆分选取。
(4)预测基准值:经过(2)和(3)的筛选、截取,剩下的样本基本上是理想的样本了,在此基础上,保持样本在日期上的顺序,按指数平滑法预测目标日期的基准值,得到基准值以后根据灵敏度或阈值系数,计算阈值上下限。
(补充说明:第四步预测基准值,有些人可能之前用过指数平滑法预测,跟第四步我们在样本权重加权时的做法很相近,但是他们预测的效果不理想,因为对样本整体没有充分的过滤选取稳定的样本集合)
动态阈值用数据统计分析的办法解决了静态阈值的误报漏报问题,节省了人工维护的成本,一定程度上降低了监控风险。不过在微量波动、持续阴跌的故障面前,动态阈值也有局限性,阈值区间收的太紧误报会增多,区间宽松就会漏报一些不太显著的故障。在review漏报case时,我们从控制图上发现这些微量波动肉眼可以观察到趋势,但是程序通过阈值区间击穿的判断方式很难控制,所以引入了均值漂移模型来寻找变点。所谓变点,就是持续微量下跌到一定时间,累积变化量到一定程度后,使得变点前后监测指标在一段时间内的均值发生漂移。
图4 均值漂移原理
从上图可以看到,均值漂移模型的算法原理,实际上是把程序不容易识别的阴跌趋势,转换成CUSUM时间序列,它的趋势很明显,在变点左侧单调增、右侧单调减,CUSUM时间序列描述了被监测时间序列每个点偏离均值的累积变化量,它的规律是从S0=0开始,到Sn=0结束,变点两侧单调变化。
CUSUM=Cumulative Sum。累积和用以在某个相对稳定的数据序列中,检测出开始发生异常的数据点。累积和典型的应用是在“改变检测”(Change Detection)中对参量变化的检测问题转化了以后,用程序求CUSUM序列上每个点的一阶导数,从持续增变为持续减即可判定为变点,至于持续增、减多少个点,由自己来设定。
关于变点检测使用的mean-shift模型,大家可以去网上找找paper,我这台电脑上找不到了,上面主要说明了发现变点的原理,通俗地讲,就是把问题转化成程序容易解决的状态阴跌线程序不容易量化衡量、判断,那么就用CUSUM控制图里的“富士山”形状去寻找,这是我个人的通俗解释。
上面说到我们使用CUSUM序列上每个点的一阶导数来判断拐点(变点)是否到来,其实图上这个例子是比较理想的情况,在我应用mean-shift模型时,遇到了一些复杂情况,比如这个图上就一个“山头尖”,但是也时候会有多个,这种情况下就要再次转化问题,比如可以把CUSUM再差分,或者以我们的做法,记录一阶导数的状态值,从连续N个正值变为持续N个负值时可以判定。
另外,变点检测的算法实现我这里不方便详细说明,其中变点在反复迭代时自己可以根据实际情况设定迭代次数和置信度,有助于提高变点发现的准确性。
变点检测弥补了动态阈值对细微波动的检测不足,这两种方式结合起来,基本可以达到不漏报和不误报的平衡,同时也不需要人工长期维护,这是智能全景监控的基础。当监控的人力成本节省了以后,理论上我们可以依赖智能监控无限制的开拓监控视野,并将这些监控报警连结起来分析。
监控项的自动发现规则,比如对维度D的指标M做实时监控,维度D下可能由1000种维度值,而且是不断变化的1000种,如何让程序自动维护监控项?你可以制定一个规则,比如指标M>X则认为需要监控(毕竟不是所有的都需要监控报警,至少在目前故障定位处理没有完全自动化的状况下,报警处理也是需要一定人力的)。在满足M>X的条件下,为了提高报警准确性,我们还需要根据重要性区分报警灵敏度,也就是对于宏观、的维度值我们希望能够非常灵敏的监控波动,而对于非重要的维度值我们预测阈值可以宽松一些,这些可以通过上面说的阈值参数来设定。
(说明:这个规则我这里只是举一个例子,各位同仁可以根据自己的实际场景去实现一些规则,比如系统运维层面的监控,有些是按照距离故障发生的速度或风险系数来判断,那么就可以围绕这种指标来制定,假如是对磁盘利用率的监控,就是容量增长速度与剩余资源比例作为参考等等)
以上条件都满足了之后,智能全景监控基本可以运行,不过我们也曾遇到一些其他的问题,比如业务方需要接入监控,但是不一定是必须要我们解析日志,他们有自己的数据,可能是数据库、接口返回、消息中间件里的消息等等。所以,我们在数据接入上采用分层接入,可以从日志标准输出格式、存储的时间序列schema约定、阈值预测的接口三个层次接入使用,这个内容将在下分享时由我的同事单独介绍。这里之所以提到,是因为全景监控接入的数据比较多,所以接入途径要有层次、灵活性。
报警的终目的是减少损失,所以定位问题原因尤为重要。Goldeneye尝试着用程序去执行人工定位原因时的套路,当然这些套路目前是通过配置生成的,还没有达到机器学习得出来的地步,不过当业务监控指标接入的越来越多,指标体系逐渐完善以后,通过统计学的相关性分析,这些套路的生成也有可能让程序去完成。这里我介绍一下,程序可以执行的人工总结处的几个套路。
(1)全链路分析
从技术架构、业务流程的角度,我们的监测指标是否正常,从外部因素分析,一般会受到它的上游影响。按照这个思路,逐一分析上游是否正常,就形成了一条链路。这种例子很多,比如系统架构的模块A,B,C,D,E的QPS。
图5 全链路tracing
(插一句,全链路分析有两种数据记录方式,要么链路每个节点内部透传,拼接成完整链路处理信息记录到终的节点日志;要么异步地每个节点各自将信息push到中间件)
(2)报警时间点上发生了什么?
这是收到监控报警后大多数人的反应,我们把运维事件、运营调整事件尽可能地收集起来,将这些事件地散点图和监测报警的控制图结合起来,就能看出问题。如果程序自动完成,就是将事件发生的时间点也按相同的方式归一化到固定周期的时间点,检查与报警时间点是否吻合。
图6 生产事件与时间序列
(3)A/B test或TopN
有些人定位问题,使用排除法缩小出问题的范围。比如在维度D上指标M有异常波动,可以将D拆分成D1,D2,D3来对比,常见的具体情况比如机房对照、分组对照、版本对照、终端类型对照等等,如果在监测数据层级清晰的基础上,我们可以一层一层的钻取数据做A/B test,直到定位到具体原因。还有一种方式,不是通过枚举切分做A/B test,而是直接以指标M为目标,列出维度D的子维度D1,D2,D3,……中指标M的TopN,找出突出的几项重点排查。
图7 A/B test or TopN
topn也是类似的。大家可以也能看出来,智能监控和辅助定位是需要一个清晰的数据层级和元数据管理系统来支撑的,这一点很基础。
(4)关联指标
不同的指标在监控中都是持续的时间序列,有些指标之间是函数关系,比如ctr=click/pv,click和pv的变化必然带来ctr的变化,这种联系是函数直接描述的。还有一些指标的关联,无法用函数公式描述,它们之间的相关性用统计学指标来衡量,比如皮尔逊系数。Goldeneye的指标关联依据,目前还没有自动分析,暂时是人工根据经验设置的,只是视图让程序去完成追踪定位的过程,比如指标M1出现异常报警后能够触发相关指标RMG1/RMG2/RMG3的检测(因为这些指标可能平时不需要7*24小时监控报警,仅在需要的时候check),以此类推逐级检测定位。
图8 关联指标
这些方式或许大家平时也尝试着去做过一些程序化的处理,我个人认为关联指标的方式,基础在于构建指标体系,这个构建过程可以是人工经验和程序统计分析的结合,指标体系至少能够描述指标的分类、数据出处、具体含义、影响相关指标的权重等等,有了这些基础才能应用统计学的分析方法完成。
平稳化的时间序列,对预测准确性有非常重要的意义,可是我们的业务监测时间序列恰好大多数都不是平稳化的,以5分钟的监测周期为力,除了大盘及监测序列,其他的时间序列都是在一定范围内正常波动但总体趋势却是稳定的。我们目前采用的方法是:
(1)滑动平均,比如波动锯齿明显,容易造成误报干扰的化,则加大监控监测周期,将5分钟提高到30分钟,相当于拟合6个时间窗口的数据来平滑时间序列。
(2)持续报警判断,如果觉得30分钟发现问题会比较晚,可以按5分钟检测,锯齿波动容易发生报警,但可以连续3次报警再发通知,这样就避免了锯齿波动的误报。
(3)对于需要均值漂移来检测细微波动的情况,24小时的时间序列本身有流量高峰和低谷,这种情况一般采用差分法做平滑处理,使用几阶差分自己掌握。Goldeneye没有直接使用差分法,因为我们已经预测了基准值,所以我们使用实际监测值与基准值的gap序列作为变点监测的输入样本。
业务监控的监测数据来源主要是日志、业务系统模块吐出到中间件、采集接口被push,从系统各模块吐出数据到中间件似乎比直接写入磁盘的IO开销小很多,不过对于请求压力比较大的系统,开旁路写出数据即使是内存级也是有一定开销的。
解决这个问题的办法是数据采样,对于在时间上分布均匀的监测数据,直接按百分比采样。
虽然数据接入是分层开放的,但是我们还是制定了标准的数据格式,比如时间序列数据存储schema,可扩展的日志消息proto格式,在这些结构化数据的定义中,可以区分出业务线、产品、流量类型、机房、版本等一些标准的监控维度信息,这样做的目的是以后可以将这些监测数据和故障定位的指标相关性分析衔接起来。
但是,这些标准化的推进需要很多参与者的认可和支持,甚至需要他们在系统架构上的重构,看似是比较困难的。
目前可以想到的办法,就是在旁路吐出监测数据时,以标准化的消息格式封装,然后保证在Goldeneye的存储层有标准的schema和接口访问。
时间序列预测模型,目前的模型只考虑了日期、节假日/周末、时间段的因素,没有年同比趋势、大促活动影响、运营调整影响的因素,需要抽象出来。
指标相关性由统计分析程序来确定。
免责声明: 凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处。非本网作品均来自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。