背景算法
任何一个产生环境的IT系统若是要长久下去,必须对其进行监控告警。常见的实现分为三个部分服务器
在过去,对于第一、2两点咱们已经积累很是多的文章和工具来谈论如何来实施一个“监控系统”。可是对于如何有效检测异常却很是缺乏行业经验的积累。若是要对有效进行量化的话主要是两个指标:微信
通常来讲,误警率能够放宽一些。虽然可能会产生狼来了的结果,可是稍微多一两条告警并不会产生什么实质的危害。须要卡控得比较严格的是漏警的状况。一旦监控系统漏警了,每每意味着一块儿责任事故和不小的损失。网络
曲线分类架构
首先,我不是一个理论工做者,对于自回归,方差等术语没有特别偏好,也没有通篇使用数学符号表达含义的表达能力。从经验观测的角度,我所知的曲线大概分为下面三类(该分类绝对不是完整分类):并发
而所须要作的监控也通常分为两类:运维
性能监控主要关注并发处理的请求数,以及与延时的关系。而可用性监控若是可能的话,首选成功率。若是咱们能够知道最近一段时间内500的HTTP返回显著上升了,基本上能够判定系统出了可用性的问题了。若是对URL作一个分类,而后某一个分类里500显著上升那么这个推断就更加精确了。这种异常检测几乎也无需太复杂的算法了,甚至一个绝对的阈值就能够了。工具
特别注意的是成功率的曲线不必定非要在一个调用的地方有一个错误码之类的东西,它能够是来自同一个流程上两个环节的数据。好比一个成功的业务过程,须要通过a,b,c三个点。咱们若是知道a点的调用量,b点的调用量,也就至关于知道了a点的成功率了。因此大部分时候,咱们是能够计算出成功率曲线的。性能
可是有的时候,好比由于组织架构的缘由,没法要求咱们的监控对象必须是某类曲线。假设咱们是一个互联网的监控服务提供商,好比监控宝。咱们没法要求咱们的用户必须提供HTTP的成功率曲线给咱们,用户只能给咱们HTTP调用的绝对数量。而后仅凭这么一条调用量的曲线来检测是否有异常。优化
本文的讨论对象是当咱们仅有“调用量曲线”的时候,如何依靠算法检测出异常。
整体思路
通常来讲,所谓的算法来实现所谓的智能,有两条道路。
对于算法检测异常出告警这件事情来讲,直觉智慧仍是占了上风的。和高维度的聚类之类的场合不一样,业务/系统指标的曲线对于异常能够很是可视化地体现出来。若是咱们以算法为第一位,直觉放第二位的话,会产生这样的状况:
从明哲保身但求无过的角度来看,算法必须可以到达和运维人员肉眼观察曲线类似的效果,不然没法向“人”交代。在知足了这个前提下,才去看那些单曲线没法感知的,可是综合多个曲线可能能够推测出的系统性故障。
如网站的访问人数之类的业务指标,自己具备周期性的波峰波谷,并且很是容易受到营销事件的影响。好比下面这个曲线
曲线自身就一直在震荡,在这样的曲线上如何检测异常?异常长什么样?好比这个
这段区间的数据掉底了(数据为零),这是很是显而易见的异常。
这个异常就须要放大了才能观察出来。在降低的过程当中,忽然陡降了一点,而后又有一个缓慢回升。
这个异常几乎肉眼没法分辨。若是不是那个时间点真的出了故障,也很难从曲线上找出来。
上面也是两个真实的故障。全部上述的故障,人的肉眼能够发现出来基本上我认为都是由于人在观察曲线的时候对于曲线的平滑和不平滑的交界处很是敏感。咱们的算法第一位的需求是要把人肉眼能够观察出来的波动,锯齿,坑都检测出来。
除了上面的这些状况以外,还有一类异常,可能就会比较难以捕捉,不如:
上面的图示一条曲线的七天叠加,也就是根据七天的规律,基本上波形是一致的。可是假如在红线处,业务曲线实际上应该有一个波峰的时候,是一条水平线过去的,那是该告警呢,仍是不告警呢?若是单纯看一根线是彻底没有平滑不平滑的问题的,由于几乎是直的。从历史统计的角度来看,这样平过去的状况确定是异常了的,须要告警出来。更极端的的一些状况,好比这个时间点有营销资源的投放,案例曲线应该有明显的抬升,可是实际曲线和往日差很少,那是否是也表明了异常?这样的一些状况的处理,我认为是算法检测的加分项,本职工做把人肉眼能够观察到的波动捕捉到就能够了,对于第二种状况就能作到多好就作到多好,实在没检测出来,也是能够理解的,由于确实很难。
statistical process control
咱们搞工程的是没有本事从新发明什么算法的。IT系统的业务数据的监控告警,看似很新鲜,其实这是一个早就被研究多年的成熟领域了。它的名字叫statistical process control(基于统计的流程控制),简称SPC。最先的奠定人是 Walter Shewhart ,他发明的Shewhart Control Chart是最先的用于告警的曲线控制图。在这个基础之上,由于工业质量控制领域用途普遍,有了很是深刻的发展。著名统计软件SAS,甚至有一个专门的工具SAS/QC用于这个领域。
最基本的shewhart control chart长成这个样子:
假设这张图表明了钻探领域里打的孔的孔径。由于钻头的大小是固定的,因此孔径应该会在一个范围上下波动。在正常的状况下,这个波动应该在一个合理的范围。在钻头损坏的状况下,波动应该会超过这个合理的范围。咱们要作的告警就是检测到钻头损坏这样的场景。怎么作?
根据shewhart control chart,首先须要根据历史的统计数据获得一个平均孔径的大小。以及在钻头良好的状况下,实际打的孔径在这个平均上下波动的方差。什么是方差?
对应的方差就是
http://en.wikipedia.org/wiki/Standard_deviation
在统计上,方差的含义就是表明了一组数据的振动幅度。利用这些钻头良好状况下的值得出的良好状况下的振动幅度,咱们就能够知道什么是“合理的范围”。好比,拍个脑壳,在两倍振幅以内是合理的。振幅也就是历史值的方差,数学符号叫sigma,因此能够说在“两个sigma”以内。因而乎,咱们能够在图上标记一个上界和下界。若是观测的值超过了上界或者下界,那么可能就是一个异常点。
用拍脑壳的方式决定“两个sigma”也是很是不科学的。实际使用中,这个n sigma的n如何肯定也是头大的问题。对于这个问题,咱们能够用反推的方法来解决。在给定历史数据的状况下,先计算出sigma,而后再计算出历史数据相对于历史的平均值每一个点是几倍的sigma。根据这些历史数据对应的sigma的倍数(统计上叫zscore),咱们能够知道大部分的历史数据都是n个sigma以内的,从而把n求出来。
shewhart control chart的问题
shewhart control chart不是包治百病的,没有任何一种control chart是适合全部类型的曲线的。shewhart control chart的适用范围是:
到这里就须要引入行业特性了。若是咱们监控的是HTTP请求量这样的曲线的话。通常来讲都会有如下特征:
而咱们的目标就是,结合shewhart control chart开创的基本思想,与咱们监控的曲线的特征,选择一个最合适的算法来检测出异常。
周期性规律
最容易被想起来利用的是周期性规律。好比,下面这个故障场景:
对比昨日和今日的曲线,咱们发如今非故障的时候两条曲线基本重合,和故障的时候下跌明显。那么很容易就想到,为何不用昨日的曲线,或者历史的平均值来预测今日的曲线呢?
的确是能够的,好比咱们能够用过去7天的平均值来做为今日的预测值。而后用过去7天的数据与预测值比较得出方差,用方差来肯定上下界。效果差很少是这样的:
首先对于时间点xx:yy,咱们用过去3天的历史数据得出一个平均值。而后咱们能够用这些平均值得出一条预测曲线,也就是上图中的绿色的线。而后用黄色的实际值作对比。咱们能够发如今业务稳定的状况下,近期的历史是能够很好的预测今天的实际曲线的。
可是实际查看历史三天的曲线,咱们能够发现上下是有波动的。这些波动就会形成方差的不稳定。
咱们能够看到,三条曲线比较重合的时候,方差很是小,而有些时间点上方差变大很是大。
方差波动的后果就是咱们很难用方差来肯定所谓的“合理范围”。
残差 = 实际值 - 预测值
波动幅度 = 残差 / 方差
上面这张图就是波动幅度的曲线,而标了红色方框的区域是故障时间段。能够看到从统计特征上来讲,是明显的,可是不够明显。用这种方式来告警,可能就会产生比较多的误警。
实际使用的过程当中能够考虑几个优化:
这些优化能够有改善,可是没法从根本上克服业务自己的不规则上下波动形成的统计特征的模糊。更要命的是由于业务常常总体上下移动,好比周末和节日。这些总体的上下会进一步扩大方差,使得原本异常的波动被认为在合理的范围以内,从而形成漏警。而咱们知道,漏警是致命的。
因此直接用历史值的周期性规律来作预测和告警是很难作的,由于业务可能会昨日重复今日,可是积极上升中的业务不会每日都同样。