业务可用性问题的快速诊断,历来是行业互联网公司面临的重大挑战,快手也不外如是。Kindling-OriginX的体系化设计理念快速打动了我们的工程师。快手随即开始了内部真实业务的验证落地;落地过程中,Kindling-OriginX能高效覆盖大部分线上问题的快速定界,其中20%可直接给出根因,缩短业务影响时长。未来,我们希望与Kindling-OriginX在异常场景和诊断效率上继续深度合作,进一步缩短业务异常的恢复时长,以及提升工程师研发幸福感。
---周辉,容器云稳定性团队负责人
Originx注:快手团队对根因的要求比较高,比如一般团队遇到请求被锁住,得到锁的代码堆栈就够了,但是快手团队要求更高,更希望知道为什么代码发生了锁住,originx目前还只能给出哪段代码堆栈导致锁住。
愿景:缩短对线上稳定性问题的定位时长,帮助业务快速止损,减轻日常问题排查的人力成本。
1.是否能在公司落地,给实际的问题诊断带来帮助;
2.为问题诊断提供借鉴思路:通过ebpf采集系统层面指标,打通业务请求链路。
结论:能够进行问题的定界。
可以对问题起到初步分支定界的作用,能初步判断出是问题哪个或哪些类别,即 :
1.CPU 执行(onCPU)
是否能够下钻
对 frequency 问题的判定效果?可以设置 frequency 吗【Originx 目前支持各种频率 CPU 采样,但是需要重启探针】
2.等待调度到 CPU(RUNQ)
较少发生,主机有较高的负载的场景
3.读写文件(VFS 的直接读写关联存储相关问题)
如何确定拿到的文件和请求是相关
Originx 通过与请求过程中的系统调用关联,按照时间能精准匹配到请求时的系统调用
4.请求下游节点耗时长(网络调用)
5.锁等待或内存 GC 类型(futex 等)
如何确定拿到的这个锁和这个请求有关
Originx 通过与请求过程中的系统调用关联,按照时间能精准匹配到请求时的系统调用
Originx 不擅长的故障种类:
1.对 CPU 算力分层类、夯机类、硬件类等问题的分析 Kindling-OriginX 诊断相对比较薄弱;
2.对Java 类服务的支持友好,接入 Kindling-OriginX 需要适配公司的 “全链路追踪系统”。
快手使用的 Originx 版本在确定故障报告时存在多种可能性,需要人为排除噪音干扰因素。
1.由于一个采样报告只能得出一种结论,故障发生所在的时间段内若干采样点产生的多个报告,可能结论不一致,需要自己来判断具体是哪方面原 因占主导,排除干扰因素;
有时会出现----未发现明显异常的结论,如

2.故障分为慢故障和故障两大类。对于慢故障,请求调用时长与历史数据相对比,发现其大于 24h 内历史 P90(或 p99,p95) 数据,将其判 定为慢故障。假设极端情况,存在故障的实例的请求时延在 24h 内一直都很高,那么后续的请求也会被判断为正常请求,产生漏判。
3.下钻诊断能力不足,当前除了对网络故障具备更细粒度的诊断(需接入 DeepFlow,在根因报告中对于对外调用网络耗时长的问题,根 因推导能够回答网络耗时分布的根因,例如是客户端网络问题还是服务端网络问题,是 RTT 问题还是丢包重传问题),其他类型问题 有待关联更多数据提供更多的下转能力。
业务请求时延指标大于 P90(或者 P95,P99 阈值),就会判定为慢请求故障。
有别于从资源视角的 USE 方法是从整理上找破绽来缩小异常的范围,给出可能性的方向,TSA 是从主体(线程)角度出发进一步明确线程时间消耗在哪里的方式。
http://u6v.cn/5VZWML

内核视角缺少业务属性,Trace-Profiling 通过 TSA 的方法论产生的数据与 Trace 打通,做到了与业务关联,这样在生产环境就可以做到某个业务因为什么原因卡住了。

skywalking 会给请求打一个 trace id,利用 ebpf 的能力将 trace 通过 PID 和 TID 底层的 syscall 相关联
利用 eBPF 技术能够深入内核,拦截线程执行用户代码的关键点位获取信息,在获得线程执行关键信息之后能够还原线程的执行过程。如 果只从线程维度看程序执行过程是很难分析出故障的,因为开发和运维的谈的故障都是 URL 维度的用户请求调用,所以光有线程维度程序 执行过程是不够的,需要和 Tracing 系统关联。当线程执行过程与 Tracing 系统关联之后,即可完整还原用户一次请求的执行过程。TraceProfiling 中关联了可观测性所需要的数据。
指标说明
Kindling-OriginX 并不直接提供 Trace 能力,而是采用接入 Trace 数据的形式,即通过接入目前成熟的 Trace 产品与提供标准接入 SDK 方 式,例如 Skywalking、OpenTelemetry、ARMS 等,利用 eBPF 能力将 Trace 数据进行扩展,将其与底层的系统调用相关联,进而实现整 的可观测性,消除程序执行与 Trace 数据中的盲区。
基于内核事件统计分析,可以形成这样的决策树,最终给出故障的根因。

程序在 CPU 资源上所消耗的时间
OnCPU
程序代码执行所消耗的 CPU cycles,可以通过程序火焰图确认代码在 CPU 上执行消耗的时间与代码堆栈。
Runqueue
线程的状态是 Ready,如果 CPU 资源是充分,线程应该被调度到 CPU 上执行,但是由于各种原因,线程并未调度到 CPU 执行,从而产生的等待时间。
网络时间属于两次 OnCPU 时间之间的 OffCPU 时间
网络时间打标过程
第一次 OnCPU 最后一个系统调用执行为 sock write 与第二次 OnCPU 第一个系统调用为 sock read,也可以理解为网络包出网卡至网络包从网卡收回的时间。
网络时间分类
DNS,TCP 建连,常规网络调用 。
属于两次 OnCPU 时间之间的 OffCPU 时间
存储时间打标过程
第一次 OnCPU 最后一个系统调用执行为 VFS read/write 与第二次 OnCPU 第一个系统调用为 VFS read/wirte。
存储时间真实情况
存储真实执行情况,由于内核的 pagecache 存在,所以绝大多数 VFS read/write 从程序视 角看:执行时间不超过 1 毫秒。
futex
通常指的是一个线程在尝试获取一个 futex 锁时因为锁已经被其他线程占用而进入等待状态的时间。在这段时间内,线程不会执行任何操 作,它会被内核挂起。
mutex_lock
线程在尝试获取互斥锁时,因为锁已经被其他线程持有而进入等待状态的时间长度。这段时间对于程序的性能至关重要,因为在等待期 间,线程不能执行任何有用的工作。

| 故障类型 | 故障案例 | 人工时长 | 使用Oirignx预计定界时长 | 召回率 | 准确率 |
| OnCPU(CPU执行)时间过长 | 代码缺陷,直播服务故障 | 16min(5+位领域专业同学投入) | 10min | 80% | 80% |
| 极高的中断负载 | 4h | 10min | 90% | 80% | |
| 等待调度到CPU时间过长 | 宿主机CPU负载过高 | 1h | 5min | 90% | 70% |
| 读写文件耗时长(IO) | P2P拉镜像卡死 | 2天(需基础平台多位高级同学参与分析,链路长) | 8min | 90% | 70% |
| 高磁盘读取负载 | 1h | 5min | 90% | 60% | |
| 请求下游节点耗时长(网络调用耗时长) | 网卡时延过长(网卡上tc注入时延) | 4h | 5min | 90% | 80% |
| epoll耗时异常 | 4h | 5min | 90% | 70% | |
| 调用中间件耗时长 | 4h | 5min | 80% | 70% | |
| 锁等待或GC | 内核osq_lock锁竞争问题 | 1周(基础平台累计10+位领域专业同学投入,蹲守凌晨业务高峰得以查明) | 10min | 80% | 80% |
| 服务异常(内核死锁问题) | 1周(基础平台累计10+位领域专业同学投入) | 10min | 80% | 80% | |
| Java锁耗时长 | 4h | 5min | 80% | 90% | |
| 内存问题 | 虚拟内存压力 | 1h | 5min | 70% | 70% |
| 用户页错误 | 3h | 5min | 80% | 80% |