程序猿

勇攀监控高峰-EMonitor之根因分析 背景

2020-05-18  本文已影响0人  阿里云技术

背景

阿里集团针对故障处理提出了“1/5/10”的目标-- 1 分钟发现、5 分钟定位、10 分钟恢复,这对我们的定位能力提出了更高的要求。 EMonitor 是一款集成 Tracing 和 Metrics,服务于饿了么所有技术部门的一站式监控系统,其覆盖了

每日处理总数据量近 PB,每日写入指标数据量上百 T,日均几千万的指标查询量,内含上万个图表、数千个指标看板,并且已经将所有层的监控数据打通并串联了起来。但是在故障来临时,用户仍然需要花费大量时间来查看和分析 EMonitor 上的数据 比如阿里本地生活的下单业务,涉及到诸多应用,每个应用诸多 SOA 服务之间错综复杂的调用关系,每个应用还依赖 DB、Redis、MQ 等等资源,在下单成功率下跌时,这些应用的负责人都要在 EMonitor 上查看指标曲线以及链路信息来进行人肉排障以自证清白,耗时耗力,所以自动化的根因分析必不可少。

根因分析建模

业界已经有好多在做根因分析的了,但是大都准确率不高,大部分还在 40% 到 70% 之间,从侧面说明根因分析确实是一个难啃的骨头。 根因分析看起来很庞大,很抽象,无从下手,从不同的角度(可能是表象)去看它,就可能走向不同的路。那如何才能透过表象来看到本质呢? 我这里并不会一开始就给你列出高大上的算法解决方案,而是要带你重新认知根因分析要解决的问题到底是什么。其实好多人对要解决的问题都模糊不清,你只有对问题理解清楚了,才能有更好的方案来解决它。

要解决什么样的问题

举个例子:现有一个应用,拥有一堆容器资源,对外提供了诸多 SOA 服务或者 Http 服务,同时它也依赖了其他应用提供的服务,以及 DB 资源、Redis 资源、MQ 资源等等;那我们如何才能够全面的掌控这个应用的健康状况呢? 我们需要掌控:

一个应用都有哪些入口?

进入每个入口之后,都可能会有一系列的如下 5 种操作和 1 种行为(下面的操作属性都是以阿里本地生活的实际情况为例,并且都包含所在机房的属性):

那我们其实就是要去统计每个入口之后的 5 种操作的耗时情况以及状态情况,以及抛出异常的统计情况。 针对远程操作其实还要明细化,上述远程操作的每一次耗时是包含如下 3 大部分:

有了上述三要素,才能去确定远程操作到底是哪出了问题,不过实际情况可能并没有上述三要素。

故障的结论

有了上述数据的全面掌控,当一个故障来临的时候,我们可以给出什么样的结论?

上述的这些结论是可以做到非常高的准确性的,因为他们都是可以用数据来证明的。 然而第二类根因,却是无法证明的:

他们一旦出问题,更多的表现是让上述 5 种操作耗时变长,并且是没法给出数据来明确证明他们和 5 种操作之间的关联,只是以一种推测的方式来怀疑,从理论上来说这里就会存在误定位的情况。 还有第三类更加无法证明的根因:

昨天的变更或者当前的变更到底和当前的故障之间有没有关联,更是无法给出一个证明的,所以也只能是瞎推测。 我们可以明确的是 5 种操作的根因,还需要进一步去查看是否是上述第二类根因或者第三类根因,他们只能作为一些辅助结论,因为没法给出严谨的数据证明。

根因分析实现

在明确了我们要解决的问题以及要求的故障结论之后,我们要采取什么样的方案来解决呢?下面首先会介绍一个基本功能「指标下钻分析」。

指标下钻分析

一个指标,有多个 tag,当该指标总体波动时,指标下钻分析能够帮你分析出是哪些 tag 组合导致的波动。 比如客户端的 DB 操作抖动了,利用指标下钻分析就可以分析出

再比如远程 RPC 操作抖动了,利用指标下钻分析就可以分析出

其实这个就是去年 AIOPS 竞赛的题目,详细见: http://iops.ai/competition_detail/?competition_id=8&flag=1 通常的方案:

  1. 对每个时序曲线都要进行数据预测,拿到预测值;

  2. 针对每个方案根据实际值和预测值的差异算出一个方案分数;

  3. 遍历所有可能性方案,挑选出分数最高的方案(通过蒙特卡洛树搜索进行剪枝优化)。

我们的方案:

  1. 确定整体的波动范围;

  2. 确定计算范围 = 该波动范围 + 前面一段正常范围,在计算范围内算出每根时间线的波动值(比如波动的方差,实际肯定不会这么简单,有很多的优化点);

  3. 对所有时间曲线进行一些过滤(比如和整体抖动方法相反,整体都向上抖动,它向下抖动);

  4. 对过滤后的时间曲线按照波动值进行 KMeans 聚类;

  5. 从排名靠前的分类中挑选出方案,为每个方案计算方案分数(这个方案个数就非常之少了);

  6. 得出分数最高的方案。

针对去年的决赛题目,我们的这个方案的跑分达到了 0.95 以上,应该就在前三名了。

根因分析流程

有了指标下钻分析功能之后,我们来看如何进行根因分析:

image

假如你有远程操作数据的 3 要素的话,那么是可以分析出:

<pre class="public-DraftStyleDefault-pre" data-offset-key="ioif-0-0" style="margin: 1.4em 0px; padding: 0.88889em; font-size: 0.9em; word-break: normal; overflow-wrap: normal; white-space: pre; overflow: auto; background: rgb(246, 246, 246); border-radius: 4px; color: rgb(26, 26, 26); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">

<pre class="Editable-styled" data-block="true" data-editor="6q2p2" data-offset-key="ioif-0-0" style="margin: 0px; padding: 0px; font-size: 0.9em; word-break: normal; overflow-wrap: normal; white-space: pre; overflow: initial; background: rgb(246, 246, 246); border-radius: 0px;">

</pre>

</pre>

假如没有相关数据的话,那就只能相对来说进行推测了(准确率也会受到影响):

<pre class="public-DraftStyleDefault-pre" data-offset-key="5cmfg-0-0" style="margin: 1.4em 0px; padding: 0.88889em; font-size: 0.9em; word-break: normal; overflow-wrap: normal; white-space: pre; overflow: auto; background: rgb(246, 246, 246); border-radius: 4px; color: rgb(26, 26, 26); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">

<pre class="Editable-styled" data-block="true" data-editor="6q2p2" data-offset-key="5cmfg-0-0" style="margin: 0px; padding: 0px; font-size: 0.9em; word-break: normal; overflow-wrap: normal; white-space: pre; overflow: initial; background: rgb(246, 246, 246); border-radius: 0px;">

</pre>

</pre>

DAL 是我们的分库分表的数据库代理层,同时起到一些熔断限流的作用,所以一条 SQL 执行时间会包含在 DAL 代理层的停留时间、以及在 DB 层的执行时间,利用指标下钻分析,可以分析出如下的一些根因:

<pre class="public-DraftStyleDefault-pre" data-offset-key="bntfl-0-0" style="margin: 1.4em 0px; padding: 0.88889em; font-size: 0.9em; word-break: normal; overflow-wrap: normal; white-space: pre; overflow: auto; background: rgb(246, 246, 246); border-radius: 4px; color: rgb(26, 26, 26); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">

<pre class="Editable-styled" data-block="true" data-editor="6q2p2" data-offset-key="bntfl-0-0" style="margin: 0px; padding: 0px; font-size: 0.9em; word-break: normal; overflow-wrap: normal; white-space: pre; overflow: initial; background: rgb(246, 246, 246); border-radius: 0px;">

</pre>

</pre>

落地情况

阿里本地生活的根因分析能力,1 个月内从产生根因分析的想法到实现方案上线到生产(不包括指标下钻分析的实现,这个是之前就已经实现好的了),1 个月内在生产上实验和优化并推广开来,总共 2 个月内实现了从 0 到 1 并取得了如下成绩

我们对定位准确性的要求如下:

每个入口服务抖动的根因很可能不一样的,比如当前应用的 SOA1 是由于 Redis 操作抖动,当前应用的 SOA2 是由于远程 RPC 依赖的其他 SOA3 抖动导致,SOA3 是由于 Redis 操作抖动导致;

准确率为什么这么高?

我认为主要是以下 3 个方面:

数据的完整度

假如是基于采样链路去分析,必然会存在因为漏采导致误判的问题。 我们分析的数据是全量链路数据转化成的指标数据,不存在采样的问题,同时在分析时可以直接基于指标进行快速分析,临时查采样的方式分析速度也是跟不上的。

建模的准确性

你的建模方案能回答出每个 SOA 服务抖动的根因分别是什么吗? 绝大部分的建模方案可能都给不出严谨的数据证明,以 DB 是根因为例,他们的建模可能是 SOA 服务是一个指标,DB 操作耗时是一个指标,2 者之间是没有任何关联的,没有数据关联你就给不出严谨的证明,即没法证明 DB 的这点抖动跟那个 SOA 服务之间到底有没有关联,然后就只能处于瞎推测的状态,这里就必然存在误判的情况。 而我们上述的建模是建立了相关的关联,我们会统计每个入口后的每种操作的耗时,是可以给到严谨的数据证明。

异常判定的自适应性

比如 1 次 SOA 服务整体耗时 1s,远程调用 RPC1 耗时 200ms,远程调用 RPC2 耗时 500ms,到底是哪个 RPC 调用耗时抖动呢?耗时最长的吗?超过一定阈值的 RPC 吗? 假如你有阈值、同环比的限制,那么准确率一定不高的。我们的指标下钻分析在解决此类问题的时候,是通过当前情况下的波动贡献度的方式来计算,即使你耗时比较高,但是和之前正常情况波动不大,那么就不是波动的根因。

速度为什么这么快?

我认为主要是以下 2 方面的原因:

业内领先的时序数据库 LinDB

根因分析需要对诸多指标的全量维度数据进行 group by 查询,因此背后就需要依靠一个强大的分布式时序数据库来提供实时的数据查询能力。 LinDB 时序数据库是我们阿里本地生活监控系统 E-Monitor 上一阶段的自研产物,在查询方面:

整体查询效率是 InfluxDB 的几倍到几百倍,详细见文章 分布式时序数据库 - LinDB https://zhuanlan.zhihu.com/p/35998778

指标下钻分析算法的高效

SOA1 的平均响应时间 t1 和 SOA2 的平均响应时间 t2,SOA1 和 SOA2 的总体平均响应时间并不是 t1 和 t2 的算术平均而是加权平均,如果是加权平均,那么久需要多存储一些额外的信息,并且需要进行额外的加权计算

实际案例

案例 1

故障现场如下,某个应用的 SOA 服务抖动上升:

image

直接点击根因分析,就可以分析到如下结果

image

AppId1 的 SOA 服务在某个机房下抖动了

这里的本地处理包含获取 Redis 连接对象 Jedis 的耗时,这一块没有耗时打点就导致划分到本地处理上了,后续会进行优化。这里没有给出详细的 Redis 集群或者机器跟我们的实际情况有关,可以暂时忽略这一点。 点击上面的每个应用,下面的表格都会列出所点击应用的详细故障信息

再比如点击 AppId4,显示如下:

image

AppId4 的 1 个 SOA 方法抖动

案例2

故障现场如下,某个应用的 SOA 服务抖动上升

image

点击根因分析,就可以帮你分析到如下结果

image

AppId1 的 SOA 服务在某个机房下抖动了

点击 AppId2,可以看下详细情况,如下所示:

image

从表格中就可以看到,根因是 DB 的一台实例抖动导致这个 dal group 所有操作抖动。

作者

李刚,网名乒乓狂魔,饿了么监控组研发专家,饿了么内部时序数据库 LinDB 的项目负责人,饿了么根因分析项目负责人,目前致力于监控的智能分析领域以及下一代全景监控的体系化构建; 林滨(予谱),饿了么监控组前端工程师,现负责一站式监控系统 EMonitor 的前端开发,旨在将繁杂的数据以高可视化输出。

查看更多:https://yqh.aliyun.com/detail/9692?utm_content=g_1000123616

上云就看云栖号:更多云资讯,上云案例,最佳实践,产品入门,访问:https://yqh.aliyun.com/

上一篇 下一篇

猜你喜欢

热点阅读