在实际工作中经常碰到这样的监控需求,重点城市的访问流量是否有大的波动、一个广告位的ecpm是否在合理的范围内、机器的CPU利用率是否正常… 经过一段时间case by case的支持,我们想到或许有通用的办法去解决这类问题。
overview
简单来说,各类监控需求都可以总结为判断一条曲线是否正常,横轴是时间,纵轴是PV、单价、CPU利用率等等的曲线。所以我们对监控流程做了这样的改进:
-
老流程:产品、运营、开发手工指定监控维度,并根据经验拍板监控规则。这样带来的问题就是监控维度覆盖面比较低、监控规则指定随意、滞后、维护成本高。
-
新流程:自动扫描监控维度,自动学习监控规则。
自动化监控
监控流程如下:
- 自动扫描监控维度(单维或交叉维度)
- 对监控时间序列曲线进行分类(平稳、自相似、非平稳)
- 对不同类别曲线采用不同监控规则(组合策略)
时间序列的自相似性
在对曲线分类之前,先介绍下我们对时间序列自相似的定义:
- 计算公式:对于时间序列t我们按周期长度n划分序列t={t1,t2…tm}, 其中m是周期数。我们采用欧式距离标准差来度量周期间的距离,用若干周期内距离平均值来度量自相似性: d(ti) = stdev(linearScale(ti)), 0 < i < n sim(t) = mean(d(t1),d(t2)..d(tn))

当一条曲线在不同周期内的距离越小,我们认为这条曲线自相似性越高。
序列分类
我们采用以下几个步骤对曲线分类为平稳、自相似、非平稳时间序列:
-
平稳曲线: 计算曲线标准差,当波动小于某个阈值,我们认为这条曲线为平稳时间序列。
-
自相似曲线: 根据监控时效性对曲线划分周期,计算曲线自相似距离,当自相似距离小于某个阈值为自相似曲线。
-
非平稳曲线: 不满足以上两个条件。
监控策略 · 常规监控
对于平稳时间序列的监控(这类指标数据一般波动较小 ,而且表现出强业务特性),我们多采用比较常规的监控策略。
-
同环比
环比 : f(t)/f(t-1)
同比 : f(t)/f(t-c)。c为周期,一般为三分钟、7天、30天等。 -
动态阈值
历史极值 :取历史指定若干周期的数据的极值,差值超过 三倍方差 则判定异常。
移动平均 :取历史指定若干周期的数据,去除极大、小值(消除历史异常点的影响)取平均。差值超过 三倍方差 则判定异常。 -
EWMA 指数加权移动平均 :取历史指定若干周期的数据,去除极大、小值(消除历史异常点的影响):
f(t)=αf(t−1)+(1−α)θt
监控策略 · 时间序列基线
自相似时间序列监控主要面向的业务场景是 分钟级 的流量监控( 波动大,而且可能极不规律 )。基于时间序列预测的基本想法是:我们用监控维度的过去 若干个周期 的时间序列去预测下一个周期,用 预测 出来的时间序列作为基线,然后拿当天的时间序列和基线进行 比较 ,超过一定范围则触发告警。解释下:
- 分钟级: 我们对流量数据按分钟切片,如果有业务波动可以在分钟内发现。
-
若干个周期: 我们忽略了季节性等因素,只考虑了一周之内的波动。所以选取了7 14天为历史周期。 - 预测: 预测方法用的是EWMA和Holt winters。
对于相邻周期内相似的时间序列(周期内的波动比较稳定),通过一般的时间预测方法都能预测出比较好的时间基线。以新闻广告的列表信息流为例,基线和实际序列的差值可以稳定在一定的范围内:
对于基线和实际序列的偏差阈值的选择有两个办法:3sigma和局部密度估计(Local Outlier Factor)。
对于相邻周期内不相似的时间序列,比较直接的想法是 转换成自相似时间序列 。
-
拉宽时间窗口 以新闻插件广告位为例,由于新闻push会带来流量的飙升,而每天push的时间点又不一样,所以流量的峰值在每天都不太相同。所以分钟级的基线预测不太理想:
如果将时间窗口拉大,比如以两个小时为例,则可以减小预测误差:
拉宽时间窗口其实是 牺牲了时效性来平滑时间序列 ,所以通常不太推荐这个方法。 -
差分时间序列:这里说的差分包括并不限于对时间序列作n阶差分、转换为增长率(同比或者环比)序列。 以新闻banner广告为例,由于每天的客户数波动较大,所以广告曲线的振幅也不一样。
但是每天曲线的升降趋势却相似,所以转换成变化速度曲线:f`(t) =( f(t)- f(t-n) )/ f(t-n), n为时间跨度。

监控策略 · 相似波
由于业务的多样性和媒体的热点流量的不确定性(比如新闻每天不定时的push),会导致很多维度的广告PV曲线并没有自相似性甚至毫无规律。
对于这类非平稳曲线,我们监控的主要目标是监控波动特性是否在合理的范围内。所以我们抽取出曲线的波,通过和历史的正常波形进行比较来判断是否异常。
波的度量
我们认为一个波的生命周期从上升率大于某个特定值为波的 上升期 ,到达 波峰 后变化率变为负进入 下降期 ,当下降率恢复到某个特定值则为到达 波谷 。在一个波的完整生命周期内我们会抽取出这个波的一些度量:
- 上升率 : 波在上升期的增长率
- 波峰 : 波的最高值
- 上半生波长 :上升期的波长
- 下半生波长 :下降期的波长
- 下降率 :波在下降期的下降率
- 波谷 :波的最低值
为了平滑小区间内的波动,我们滑动一个固定宽度的时间窗口。把一个窗口内的点 拟合成一条直线 。
波的监控
在波不同的生命周期内我们会触发不同的监控策略,最后组合多个策略判断波动是否异常:
- 上升率 :上升期内上升率如果超过历史同期正常上升率的极大极小值,则标记异常。
- 波峰 : 波峰和历史同期均值的差值超过3个标准差,则标记异常。
- 上半生波长 :上半生波长和历史同期均值的差值超过3个标准差,则标记异常。
- 下半生波长 :下半生波长和历史同期均值的差值超过3个标准差,则标记异常。
- 下降率 :下降期内下降率如果超过历史同期正常下降率的极大极小值,则标记异常。
- 波谷 :波谷和历史同期均值的差值超过3个标准差,则标记异常。