智能运维|解放程序员,一个工具就能锁定程序故障(下)

核心提示在上一篇《智能运维 | 解放程序员,一个工具就能锁定程序故障》文章中我们主要介绍了一种在服务发生故障时自动排查监控指标的算法。算法的第一步利用了概率统计的方式估算每个指标的异常分数,第二步用聚类的方式把异常模式相近的实例聚集在一起形成摘要,

在上一篇文章《智能运维|解放程序员,一个工具就能锁定程序故障》中,我们主要介绍了一种在服务失效时自动检查监控指标的算法。该算法的第一步使用概率统计来估计每个指标的异常得分,第二步使用聚类来聚集具有相似异常模式的示例以形成摘要,第三步使用排序来向工程师推荐最有可能是根本原因的摘要。

由于运维场景的特点是数据量大,但校准量少,成本高且容易出错,所以我们综合运用概率统计、无监督学习和监督学习的方法来解决问题,在最小化训练数据的前提下取得了较好的效果。

在离线实验的70个故障案例中,我们的算法可以将60个案例的根本原因总结排在第一位,可见算法的强大生命力。

异常检测算法

异常检测算法是我们整个自动检查和监控指标工具的核心,它需要解决跨实例和指标的异常程度比较问题。这就涉及到一个起源的问题:什么是异常?

请闭上眼睛思考1分钟,然后往下看。

你觉得这个问题好像很难回答?笔者也为很多人的这个问题感到惋惜。有人说不正常就是不正常,但不清楚什么是正常。有人说,你给我一些具体的数据,我就能告诉你哪些是不正常的,但是没有具体的数据,我就没法抽象的说出来。别人一上来就说,这个问题从来没想过。

所谓“罕见而奇怪”,就是因为罕见或者根本没见过而感觉奇怪。还有一句话叫“我们空习惯了”,意思是每天看到你,所以我习惯了。这两个成语表达的是不寻常的东西容易被视为奇怪,而平常的东西并不奇怪。换成数学的语言:小概率事件不正常,大概率事件正常。虽然这种说法并不是100%准确,但大多数时候还是这样。因此,测量指标的异常程度可以通过观察指标值的概率来描述。既然是概率,当然可以比较,可以跨实例跨指标比较。

指数的观测概率可以从许多不同的角度进行建模和计算。在这里,我们主要关注突然增加和突然减少。指标的突然增减很好理解。例如,工程师很容易同意图1中的指标是不正常的。另一方面,很多失败会体现在某些指标的忽高忽低上。最重要的是很容易计算出指标突增突降对应的观测概率,非常适合我们需要扫描大量指标的场景。

图1 CPU _ WAIT _ IO突然增加说明有磁盘竞争。

需要收集一些数据来计算突增突降的观测概率。假设故障从机

时间开始发生,我们在区间内收集某个指标。

数据输入

和间隔

数据输入

。明显地

是故障发生前的数据,如果

小于故障持续时间,

是数据中的错误。一般来说,我们可以

让它变得更长,以提高概率的准确性。但是

必须尽可能的短,这样才能尽快出诊断结果。

怀孕了

,我们可以比较这两组数据,并产生观察概率。用数学的语言来说,就是计算。

那就是,在

之前一直在观察。

前提是观察到后一瞬间。

的概率。

首先,我们计算单点概率。

。假设

是一个随机变量。

生产一个样品,我们可以通过

估计

分布,然后根据

的分布计算

观察概率。因为大多数指标的值是连续的,所以

也应该是连续的随机变量,对应的概率就变成了

溢出概率:

下溢概率:

当...的时候

比较

高概率很小,说明

太大,对应突然增加;当...的时候

比较

小概率很小,说明太小,对应的是突然下跌。假设

是由彼此独立的部分组成的

由具有相同分布的随机变量产生的样本,其设定概率为

溢出概率:

下溢概率:

为了便于计算和人们查看,通常计算概率的对数。概率的对数都是负数,自然会看到正数,所以我们把概率的对数的负数作为异常分数。

溢出分数:

下溢分数:

剩下的问题是如何确定。

的分布。常见的方法是假设它服从正态分布,并利用

估计正态分布的两个参数

最终计算基于

计算测试

的统计

服从以0为均值,1为标准差的正态分布。

。单点的上溢概率和下溢概率可以用正态分布来计算。

顺便说一下,

大于3或者小于-3的概率大概是0.13%,已经很小了。因此,在异常检测时,经常使用3作为统计量。

的阈值。即将发生

常见方法。

这种方法最大的问题是很多指标的值不服从正态分布。例如,CPU_IDLE是一个值在0和1之间的指示器。当根据上述方法计算时

通常会小于0,并且

往往会大于1,以至于指标的异常程度无法正确反映。因此,我们采用了核密度估计的方法。

核密度估计是一种估计概率密度函数的非参数方法,适用于未知分布类型的随机变量。基于观察样本

,

的概率密度函数可以估计为

在…之中

这是一个内核函数。如果核函数是正态分布的,那么

该参数大约接近于

的标准偏差

,所以概率密度函数变成了

对于CPU_IDLE这样的指标,我们可以用Beta分布作为核函数,当

这里

是一个正数,用于控制贝塔分布的形状。

越大,贝塔分布越尖锐;

越小,贝塔分布越平坦。

有了概率密度函数,就可以通过积分计算出单点的概率。

在计算每个指标的异常分数后,我们将属于同一实例的指标的异常分数组合起来,形成一个异常分数向量。

这里的每个下标对应一个指标。

为了便于工程师阅读,我们需要对具有相似异常模式的向量进行聚类。聚类是无监督学习的典型方法之一。与监督学习不同,聚类不能通过对样本的标注来控制输出结果,所以控制聚类方向的核心在于距离函数和聚类算法。

距离函数有多种选择。通常有欧几里德距离,或者更一般的。

距离;计算向量间夹角的余弦距离;甚至相关系数也可以用来度量两个向量之间的距离。当属于同一模块的不同实例的负载几乎相同时,欧几里德距离应该给出好的结果。但是在实际中,实例之间的负载总是会不一样,这使得同一个异常模式在不同的实例中表现出不同的异常分值,欧氏距离会降低聚类效果。这时候,相关系数是个不错的选择。Pearson Correlation计算两个例子异常分数的相关性,可以忽略数值的绝对水位。Spearman Correlation首先根据异常程度对一个实例索引进行排序,然后计算两个实例的异常程度之间的相关性。在我们的实验中,Spearman相关的效果很好。

在聚类算法中,由于我们无法预先知道存在多少种不同的异常模式,K-means显然不是一个好的选择。层次聚类和DBSCAN不需要预先设置聚类数,所以更能满足我们的需求。在实验中,我们采用了DBSCAN,确实得到了很好的效果。

集群化,理论上我们可以把所有模块的所有实例都集群在一起。在实验中,我们发现这个聚类结果有时候还可以,可以发现跨模块的问题,比如网络故障影响多个模块之间的通信,最终导致整个系统的故障。但是,这种方法的输出在很多情况下并不好。因此,我们采用相对保守的方式,将集群限制在属于同一个模块和同一个机房的实例中。

分类

聚类算法将具有相似异常模式的示例聚集在一起,以形成摘要。每个摘要都有一定的可读性。我们只需要把属于根本原因模块的摘要放在最上面,推荐给工程师,就大功告成了。

排序算法考虑了三个因素:

1.摘要中的例子数量。例子越多,影响越大,越有可能是根本原因。2.摘要中异常分数特别高的指标数。指标越多,越有可能是根本原因。3.摘要中各示例指标的平均异常得分。平均分越高,越有可能是根本原因。

计算上述三个因子的值,形成三个特征。我们只需要用通常的方式训练一个ranker。

表1中的错误!找不到引用源。中所示的故障案例的自动分析结果。

标准中的第一列是摘要所属的模块和机房。第二栏是摘要中的例子在同一个模块、同一个机房的例子中所占的比例。第三列是摘要中的示例列表。第四列是异常分特别高的指标及其异常分。

我们的算法第一次真正在根本原因模块G中推荐了一个抽象。从第四栏的内容可以看出,机房DC1的G模块因为某种原因过载了。G过载后,对上游模块的响应变慢,使得同一个机房的E模块不得不维持更多的RPC连接,于是同一个机房的E模块被秒走,网络连接数相关指标确实异常。

表1故障排除和分析结果

总结

故障诊断作为智能运维中典型的复杂场景,一直是众多运维工程师的努力方向。本文介绍的指标自动检查算法表明,除了机器学习,概率统计在智能运维中也将占据重要地位。

如果您对故障诊断的研究有任何想法和问题,请留言与我们交流。

作者简介

云运营高级数据架构师

负责云智能运维算法和策略的研究,致力于用算法和数据的力量解决运维问题。

 
友情链接
鄂ICP备19019357号-22