本文聚焦于线上应用的风险管理,特别是针对“错”(程序运行不符合预期)和“慢”(性能低下或响应迟缓)两大类问题,提出了一个系统化的根因诊断方案。
线上应用风险主要分为“错”、“慢”两大类。其中“错”的原因通常是程序运行不符合预期,比如 JVM 加载了错误版本的类实例,代码运行进入异常分支,环境配置错误等。而“慢”的原因通常是资源不足,比如突发流量导致 CPU 飙升,数据库大查询导致连接池打满,内存泄漏导致持续 FGC 等等。
无论是“错”问题,还是“慢”问题。从研发运维视角,都希望能够快速止损、定位根因、消除隐患。然而,面对复杂的应用间依赖,如何抽丝剥茧快速定位异常节点,深入分析异常背后的根本原因,并在极短的时间完成定位与恢复动作,每一步都面临巨大的技术挑战。
根据近十年 APM 领域产品研发与客户支持经验,总结沉淀了一套行之有效的错慢请求根因诊断方案,主要包括以下几点:
1.
根据 Trace 链路及关联数据定位错慢请求异常对象
:链路追踪可以跟踪一次请求在分布式系统中的流转路径与状态,同时将这次请求发生过程中的日志、方法栈、出入参、异常堆栈等数据精准关联,实现异常代码行级定位。比如用户在APP下单超时,通过前后端链路追踪结合方法栈,最终定位到A应用B接口C方法耗时超过3s,影响了终端客户体验。
2.
根据异常对象关联的实体数据分析真实根因
:
代码执行报错或缓慢只是问题表象,导致变化发生的原因可能是一次未经灰度验证的应用发布,或是底层基础设施故障,亦或是业务流量突增导致共享资源不足。这些信息与异常对象存在着直接或间接的关联关系,需要构建更广泛的跨域实体关联才能完成深层次定位。比如A应用正常访问数据库B突然出现许多慢SQL,通过数据库客户端与服务端实体关联,就能快速定位到数据库服务端连接池打满(受到C应用大查询影响)。
3.
高质量数据+领域知识+大模型算法实现智能根因诊断
:线上系统的复杂性,决定了根因诊断会涉及海量实体的多模态数据综合分析,对于数据丰富度、质量、排查经验与时效性均有极高的要求。构建统一可观测平台实现端到端全栈数据采集,遵循一套语义构建统一实体关系模型,再结合LLM大模型编排与领域知识库,最终实现面向错慢诊断等经典运维场景的自动化归因。
基于 TraceId 可以实现请求粒度的轨迹回溯与数据关联。但是,错慢请求的诊断流程略有不同:慢请求诊断的关键点在于找到真正耗时的代码行。而错请求则分为服务报错与业务报错两类,前者依赖异常堆栈,后者需要结合业务日志与方法入参进行辅助判断。
慢请求诊断的难点在于,如何找到影响总体耗时的关键路径,并细化到方法粒度(代码行)指导研发排障。传统的链路追踪技术都是通过插桩法实现通用接口埋点,无法抓取完整的本地方法栈。因此,一线开发人员经常遇到定位到慢接口,但是不知道内部方法耗时,难以优化代码解决隐患。
例如阿里云 ARMS 提供的持续剖析-代码热点功能,可以常态化自动抓取慢请求的完整本地方法栈,实现行级代码定位,大幅提升慢请求定位效率,如下所示。
1. 根据应用、接口、耗时等参数筛选出满足条件的调用链。查看慢请求分布特征,比如是否集中在某一台机器(疑似单机故障),再展开分析具体的调用链详情。
2. 根据调用链瀑布图定位到影响总体耗时的关键服务接口,完成问题初步定界。
3. 根据代码热点记录的当次慢请求关联的完整本地方法栈,直接定位业务异常代码行,指导研发同学优化代码。
通过以上步骤,我们实现了基于链路与关联数据(方法栈)定位慢请求异常代码行的过程。研发同学拿到慢方法的具体代码行及上下游调用关系,就可以通过优化代码逻辑解决慢请求问题。
错请求可以分为请求报错与业务报错两类。前者属于程序运行不符合预期,比如 HTTP 5XX 错误抛出 RuntimeException。而后者则是业务逻辑不符合预期,比如用户下单使用优惠券失败,原因可能是优惠券已失效,但是服务调用是正常的。针对不同类型的错误,排查流程略有差异,但关键操作包括以下几类:
1.
链路与日志双向关联跳转:
排查系统报错时,可以从微服务调用视角找到错误调用链,再查看关联的应用日志。而排查业务报错时,可以先检索应用日志里的业务关键词,再通过日志关联的TraceId 反向查询上下游信息。
2.
链路关联异常堆栈:
以 Java 应用为例,系统报错通常会抛出特定异常(包含详细的错误原因与调用堆栈),通过 TraceId 准确关联当次请求的异常堆栈,可以加速研发排障效率。
3.
链路关联请求出入参数:
不同的请求入参可能会影响程序执行分支,比如不同渠道优惠策略有差异。因此,在排查一些疑难问题时,还需要结合当次请求的方法入参进行判断。而出参由于数据量不可控(比如一次数据库大查询返回几万行数据),通常只记录 ResponseSize 而不是完整结果。
通过链路与日志、异常堆栈、请求参数等信息的关联,我们可以精准识别每一次请求关联的异常信息,有效提升错请求诊断效率。
通过链路及其关联数据,我们可以快速定位错慢请求的异常对象,但是导致问题发生的真实根因,往往更加复杂,不局限于应用进程内。为了快速止血或彻底根治,我们需要采集更大范围的观测数据,并通过统一实体模型构建异常对象与根因之间的联系。
最简单最常见的实体关联,就是在相同时间范围内,同一台主机实例的数据关联。比如 A 应用部署的某台物理机出现硬件故障,故障期间没有及时切流导致路由到该机器的所有流量全部超时报错,最终导致业务受损。以 Java 应用为例,ARMS 提供了丰富的主机监控数据用以诊断单机问题,包括主机/Pod系统指标、JVM GC/堆内存、线程池/连接池等。
更广义的实体关联,还包括移动终端、网关、数据库、K8S 工作负载、CI/CD 任务甚至是 Git 代码提交人。这些跨域实体及其关系最终构建了一张覆盖端到端全栈 IT 软硬件设施的数据观测网络。任意实体的变化会导致上下游关联实体的联动反应,例如 A 同学执行了一次数据库 B 实例的索引变更,导致 C 应用出现大量慢 SQL,进而影响 D 终端用户下单失败。通过构建统一实体关系模型,可以打通跨域数据连接壁垒,提升根因诊断效率,并为智能诊断打下坚实的基础,如下图所示。