1 故障定位的背景
在微服务和云原生环境下进行故障定位通常会面临以下困难://文章中,“可能”二字用的比较多,建议优化成通常或其他的词语
-
分布式系统复杂性:微服务架构中,系统被拆分为多个小型服务,每个服务通常运行在不同的容器或虚拟机中,甚至可能部署在不同的云平台上。当一个问题发生时,需要跨多个服务、多个主机或者多个云服务来追踪问题的根源,这增加了故障定位的复杂性
-
服务间依赖性:微服务架构中,各个服务之间通常通过API或消息传递进行通信。如果某个服务出现问题,可能会影响到其它依赖的服务,造成级联故障。因此,需要在故障排查过程中考虑到服务之间的依赖关系
-
日志和监控的管理:在云原生环境中,服务的日志和监控数据通常分散在多个地方,如不同的日志文件、监控系统或者日志聚合工具中。聚合和分析这些数据以诊断问题,特别是跨服务或跨云平台的问题,通常需要复杂的工具和技术
-
动态扩展和容器化挑战:云原生环境中,服务通常会根据负载动态扩展或缩减,容器化技术如Kubernetes使得服务的部署和运行更加灵活。然而,这也增加了故障定位的难度,因为服务的实例数量和位置可能在时间和空间上变化
-
复杂的网络结构:云原生应用通常涉及复杂的网络拓扑,包括虚拟私有云、负载均衡器、服务网格等。网络问题如延迟、丢包或者配置错误,可能导致服务间的通信问题,从而增加了故障定位的复杂性
-
自动化运维的影响:虽然自动化运维能提高效率,但在发生故障时,可能需要手动介入来获取更详细的诊断信息或执行特定的故障排除步骤,这需要管理和协调自动化和手动操作之间的平衡。
综上所述,微服务和云原生环境急需一套可落地性好的故障定位系统
2 业界解决方案
业界在故障定位领域的解决方案也尝试了很多种,这里先简单介绍如下3种
-
AI主导的解决方案
-
告警主导的解决方案
-
Tracing主导的解决方案
2.1 AI主导的解决方案
AI领域的不断进步和发展,逐渐让人们觉得AI貌似也可以在根因分析上发挥出价值,构建出一套AI主导的解决方案,该解决方案有如下特点:重AI算法
-
认为专家经验太过琐碎,数据也多,比如主机上有磁盘、网络等数据,面向专家经验和数据来做定位太累
-
想不用在乎各种场景下数据源背后的细节知识,找到一种统一的AI方式来解决,比如从历史故障中自动挖掘出一些数据之间的关联和特点,培养自学习能力,以供下次复用
//这里建议也拉几个垫背,最好是国外的方案厂商,比如moogsoft\bigpanda之类的。建议也找一家具体说明一下他的搞法,不然这块感觉没有你的论点支撑。
该方案通常的问题点:
-
当前AI还未能达到预期的效果,就导致整体不理想,不如普通的专家定位
-
一线工程师发现,AI方案并不符合他们的常规排障逻辑,AI不理解他们,给出的结果不可解释,是个黑盒
-
AI主导的运维方案,往往普世性不强,甲方的使用门槛过高,不容易形成产品化交付
2.2 告警主导的解决方案
参见腾讯的AIOPS实践,以服务拓扑图+服务告警为基石进行定位
//这里再多做些方案介绍
该方案通常的问题点:
-
更多还是定界到服务
-
定位质量依赖告警的质量:服务拓扑基本上目前都可以做到并且比较准确,但是由于服务的响应时间或者异常量的阈值各自不一致,容易出现同样是有问题,有些服务告警了,但是有些服务没告警,因此告警的质量会影响定位的质量
2.3 Tracing主导的解决方案
参见去哪儿网根因分析实践,通过Tracing定位到根因服务+通过Metric指标对服务进行下钻分析
//这里再多做些方案介绍
该方案通常的问题点:
-
Tracing链路很多,要进行聚合分析就要涉及到采样,采样之后的数据相对不可靠,可能会有误导
-
Tracing聚合分析相对比较耗资源,并且速度慢
-
分析的数据粒度太粗,没有精细化到接口级别
3 第一性原理
从上面可以看到故障定位其实比较宽泛,不同人的理解最后的做法可能完全不一样。这么多理解中到底有哪个是最靠近本质的呢?这个事情就必须要从第一性原理说起,即回归事情的本质。
第一性原理是特拉斯创始人马斯克极力推崇的决策框架,认为这种方法能够帮助他能够从事物的本质出发,找到解决问题的新思路和新方法。。比如十几年前,传统锂电池组价格曾长期居高不下,这很大程度影响了特斯拉电动车的大众化之路。于是,马斯克回归电池组的最基本要素,思考电池组是由哪些材料组成的?这些原料的市场价格是多少?结果他发现,如果从伦敦金属交易所购买电池组所需的碳、镍、铝等原材料,再由特斯拉自己建厂研发制造,而不是直接购买供应链产品,电池投产之后的价格可以下降30%。
这种思维方式就是第一性原理,用物理学的角度看待世界,将复杂的问题分解为最根本的真理,然后从头开始推理、加工,创造出想要的结果。这种思维模式更容易有所突破与创新
//第一性原理更倾向指打破知识的藩篱,回归到事物本源去思考基础性的问题,在不参照经验或其它的情况下,从物质和世界的最本源出发思考事物.XXXXX
//建议这里再加上一段,带入到故障定位的话题。
比如,我们作为一线运维工程师,抛开现有的各供应商解决方案的教育引导,重新从故障本身出发来思考问题,不参照任何供应商已有的经验。不管是AI、算法还是规则,都只是故障定位这件事情上的工具。要想定位故障,首先我们要足够深入的理解故障本身。XXXXXXXX
//第二章给出了三种方案的介绍,那我们的这种方案,有没有必要给一个标签??
4 故障定位的认知
故障定位也是如此,看起来比较庞大繁杂,无从下手,那我们就来实践下第一性原理
我总结出如下几个本质问题
-
故障是怎么产生的
-
如何能定位故障
-
定位过程中有哪些难题
//这里可以理解为你的行文概要。下面的结构建议也参照这三个概要来组织
4.1 故障是怎么产生的
我对这个问题的回答:故障是由代码产生的,看起来是一个非常对的废话,我们继续往下分析//这里的故障比较宽泛,容易被挑战。比如硬件的故障。所以本篇要框定我们研究的故障的范围。
-
代码都有哪些分类
-
每个分类都会产生哪些故障
-
每个分类需要采集什么数据才能定位
-
每种数据需要什么工具能够采集
先对上面的问题进行粗浅的回答
代码的分类 | 产生的故障 | 需要采集的数据 | APM | eBPF | APM+指标采集 | APM+eBPF |
业务程序代码 | 业务自身异常的故障 | 业务异常堆栈 | ✅ | ❌ | ✅ | ✅ |
业务自身的调用量、耗时、错误等故障 | 任意业务方法的指标数据和Trace数据 | ✅ | ❌ | ✅ | ✅ | |
任意业务方法的参数 | ✅ | ❌ | ✅ | ✅ | ||
任意异步代码的串联 | ✅ | ❌ | ✅ | ✅ | ||
内部框架代码 (无外部访问的框架) | 缓存池、对象池、连接池、线程池的故障 | 缓存池、对象池、连接池、线程池的指标数据 | ✅ | ❌ | ✅ | ✅ |
缓存池、对象池、连接池、线程池的Trace数据 | ✅ | ❌ | ✅ | ✅ | ||
外部框架代码 (有外部访问的框架) | 框架的配置参数故障 | 框架client的内部逻辑 | ✅ | ❌ | ✅ | ✅ |
框架的远程访问故障 | 框架client通过socket访问外部 | ✅ | ✅ | ✅ | ✅ | |
语言代码 | jvm相关的故障 | jvm相关指标数据,比如gc、类加载、jvm内存 | ✅ | ❌ | ✅ | ✅ |
操作系统代码 | 延迟、丢包、乱序等网络故障 | DNS、TCP、网卡等的指标数据 | ❌ | ✅ | ✅ | ✅ |
DNS、TCP、网卡等的Trace数据 | ❌ | ✅ | ❌ | ✅ | ||
CPU、内存、磁盘等故障 | 每个进程的CPU、内存、磁盘IO等数据 | ❌ | ✅ | ✅ | ✅ | |
k8s | 延迟、丢包、乱序等网络故障 | CoreDNS、Pod网卡、Node网卡等的指标数据 | ❌ | ✅ | ✅ | ✅ |
CoreDNS、Pod网卡、Node网卡等的Trace数据 | ❌ | ✅ | ❌ | ✅ |
从上面可以看出
-
故障是讲究场景的。要想去定位故障,就需要先去了解该故障的场景
-
每个采集工具都有适合自己的一批场景,没法做到所有场景,要想做到所有场景,那么就需要组合多套采集工具
同时对采集工具可以得出的结论:
-
APM擅长业务程序内部的数据采集
-
eBPF擅长业务程序外部的数据采集
-
要想做到更严谨的故障定位,那么就需要APM+eBPF采集的全集
我们知道了使用不同的采集工具来采集对应的数据,那么数据质量如何保证呢?即如何采集高质量的数据呢?
4.2 采集高质量的数据
以APM中访问mysql数据库为例,该场景的整体逻辑如下所示:
核心步骤如下所示
-
步骤1:从DataSource连接池中获取可用连接
-
1.1 可能创建新的连接
-
1.2 可能一直等待,直到有空闲连接可用
-
-
步骤2:使用连接执行sql语句
那在这个具体场景下就有很多种故障可能性,如下所示:
故障编号 | 故障一级分类 | 故障二级分类 | 数据支撑 | OpenTelemetry | Skywalking | Datadog |
1 | 连接类的故障 | 创建连接失败 | 获取连接的span增强 | ❌ | ❌ | ❌ |
2 | 创建连接耗时增大 | ❌ | ❌ | ❌ | ||
3 | 等待可用连接耗时高 | ❌ | ❌ | ❌ | ||
4 | 最大连接数太小 | 连接池的监控 和Trace关联起来 | ❌ | ❌ | ❌ | |
5 | database类的故障 | 整个database耗时增长 | 执行sql的span增强 | ✅ | ✅ | ✅ |
6 | 整个database失败数增长 | ✅ | ✅ | ✅ | ||
7 | 某个实例-整个database耗时增长 | ✅ | ✅ | ✅ | ||
8 | 某个实例-整个database失败数增长 | ✅ | ✅ | ✅ | ||
9 | 某类sql的故障 (select、update、delete) | 某类sql耗时增长 | ✅ | ✅ | ✅ | |
10 | 某类sql失败数增长 | ✅ | ✅ | ✅ | ||
11 | 某个实例-某类sql耗时增长 | ✅ | ✅ | ✅ | ||
12 | 某个实例-某类sql失败数增长 | ✅ | ✅ | ✅ | ||
13 | sql的故障 | 某个sql执行的耗时增大 | ✅ | ✅ | ✅ | |
14 | 某个sql执行的失败次数增多 | ✅ | ✅ | ✅ | ||
15 | 某个sql更新的行数过大 | 获取更新行数、读取行数 | ❌ | ❌ | ❌ | |
16 | 某个sql读取行数过大 | ❌ | ❌ | ❌ | ||
17 | 某个实例-某个sql执行的耗时增大 | 执行sql的span增强 | ✅ | ✅ | ✅ | |
18 | 某个实例-某个sql执行的失败次数增多 | ✅ | ✅ | ✅ | ||
19 | 某个实例-某个sql更新的行数过大 | 获取更新行数、读取行数 | ❌ | ❌ | ❌ | |
20 | 某个实例-某个sql读取行数过大 | ❌ | ❌ | ❌ |
只有采集了上述数据,才能将日常的故障基本都覆盖到,目前开源的APM只是采集了基本的数据,即只能定位到一部分故障,另一部分故障没法定位到
4.3 定位流程
采集了场景下的高质量数据之后,我们如何来串联各个场景进行定位呢?这就需要如下的空间地图
-
水平方向:是服务之间的访问拓扑
-
垂直方向:是服务下的服务实例的部署拓扑
这个空间地图就是将所有的场景进行串联起来,包含APM、Metric、Log、NPM数据等等,定位思路如下:
-
先从水平方向定位定位到某个具体的服务
-
然后再从垂直方向定位定位到具体的实例、或者实例所在的资源问题、或者服务自身代码
有了高质量的数据,加上我们对场景的认知,加上空间地图,基本上可以做到人工定位了,但是人工定位存在哪些问题呢?
-
不是每个人都具备专家级的排障能力
-
排障专家也是细分领域的,很难全能
-
要分析的数据太多,人工分析速度太慢
因此必须要引入算法来实现自动化分析
4.4 算法自动化
使用算法会面临哪些难题?
-
异常检测算法:比如每个服务的平均响应时间各不相同,如何自适应判定服务的平均响应时间波动上升了?
-
使用比例?使用阈值?都会有很大的限制,无法做到普适性
-
-
指标下钻算法:比如某个服务访问DB的平均响应时间上升?到底是哪些维度导致的呢?
-
是某个database的访问都上升?
-
只是某个table的访问都上升?
-
只是Delete类型的SQL都上升?
-
只是某个sql的访问都上升?
-
只是某个服务实例才上升?
-
这2个算法问题解决了,基本才能实现自动化的故障定位。现在自动化的故障定位实现了?如何验证算法的普适性呢?比如很可能在耗时波动1000ms的故障可以定位,可能波动500ms的故障就定位不到了,那么就需要造出各种不同程度的故障来验证算法的普适性,这就又引出了混沌工程
4.5 混沌工程验证
阿里巴巴开源了一个混沌工程平台chaosblade-box,可以在上面制造出各种场景下的故障,以及可以制造出各种不同波动程度的故障,如下所示:
-
可以自动触发各种类型的故障,7*24小时不间断制造故障,来验证根因分析的准确性
4.6 定位结果的呈现
有些定位方案,只能给出最后的一个结果,无法展示推理过程,这种就导致用户不太能验证最后的结论到底是否准确。根据我们的上述方案,其实完全可以做到定位流程的白盒化
-
可以展示出服务的故障树(只展示跟故障相关的服务)
-
可以展示出每个服务的故障原因(比如DB故障中,可能是某个SQL耗时增多的故障)
5 故障定位的实践
在第一性原理的指引下,经过我们一步步的详细分析,最终给出了解决方案,接下来就来看下实践效果
//我觉得这里是不是要这样来介绍实践。依据第一性原理,我们设计了一套故障定位的引擎。然后对这个引擎做个基本介绍。
再往下就是以这个引擎为基础,我们的定位实践。
5.1 SQL读取行数增多的案例
通过混沌工程注入某个SQL读取行数增多的案例,根因分析结果如下
故障详情如下:
-
先给出某个SQL的平均响应时间上升
-
最后也给出平均响应时间上升的原因是:SQL的读取行数增多导致的
5.2 多个耗时故障的案例
通过混沌工程注入DB某个sql更新行数增多的故障、Redis某个命令耗时增多的故障
根因分析结果如下:能够自动识别出是2个故障,并形成对应的故障树
根因详情如下所示:
5.3 多个错误故障的案例
通过混沌工程注入DB某个sql错误增多的故障、Redis某个命令错误增多的故障
根因分析结果如下:能够自动识别出是2个故障,并形成对应的故障树
根因详情如下所示: