Todos
- [ ] 【无损统计】调用链日志成本太高,开启客户端采样后,监控图表就不准了,如何解决?
- 调用链日志是与流量是正相关的,To C 类业务的流量非常大,调用链全量上报与存储的成本会非常高,但是如果开启客户端采样后,又会面临统计指标不准确的问题,比如采样率设置为 1%,一万次请求仅会记录其中一百条,根据这一百条日志聚合出来的统计数据会导致严重的样本倾斜问题,无法精确反映实际服务流量或耗时。 - 为了解决上述问题,我们需要支持在客户端 Agent 进行无损统计,同一个指标在一段时间内(通常为15秒)不论请求多少次,都只会上报一条数据。这样统计指标的结果就始终是精准的,不会受到调用链采样率的影响。用户可以放心的调整采样率,调用链成本最多可降低 90% 以上。流量和集群规模越大的用户,成本优化效果越显著。
- 变更更三板斧“可灰度、可监控、可回滚”,是保障线上稳定性的重要准则。
链路倾斜采样,记录更有价值的数据
链路数据的价值分布是不均匀的。 据不完全统计,调用链的实际查询率通常小于百万分之一,也就是说,每一百万条调用链,只会有一条被实际查询命中,其他链路几乎都是无效存储。全量存储调用链不仅会造成巨大的成本浪费,也会显著影响整条数据链路的性能及稳定性。因此,链路采样(Trace Samplling)的理念随之诞生。
早在 Google Dapper 论文问世的时候,就提出了基于固定比例进行链路采样的方法,并在 Google 内部生产系统得到了实践检验。比如每 1024 条链路采样记录其中一条,采样比例为 1/1024。但是,固定比例采样仅仅解决了控制链路开销的问题,而忽视了链路价值分布的不均匀性,关键链路与普通链路被采样的概率都是相同的,这就导致许多针对关键链路的查询结果出现未命中,极大影响了问题排查的效率。
那么,我们能否提前预测用户行为,只记录会被查询的链路呢?100% 精准预测非常困难,几乎难以实现,但是根据历史行为和领域经验进行推测,优先记录查询概率更大的链路是比较可行的一种降本方案,这就是链路倾斜采样。
链路倾斜采样通常是针对特定的链路特征(如错、慢、核心接口或自定义业务特征)设置较高的采样比例(如100%)或流量阈值(如前N条/分钟),不符合关键特征的链路以极低的比例采样(如1%)甚至不采样。如下图所示的阿里云链路追踪自定义采样配置页面,用户可以根据自身需要自由定制特征采样策略,在保证较高的查询命中率(如50%+)的前提下,链路数据实际存储量可以达到原始数据量的 5% 左右,极大的节省了服务端持久化存储的成本。更多链路采样策略将在实战篇进行详细介绍,比如动态采样。
筛选更更有价值的数据
链路数据的价值分布是不均匀的。 据不完全统计,调用链的实际查询率小于百万分之一。全量存储数据不仅会造成巨大的成本浪费,也会显著影响整条数据链路的性能及稳定性。如下列举两种常见的筛选策略。
- 基于链路数据特征进行调用链采样上报(Tag-based Sampling)。 比如错/慢调用全采,特定服务每秒前N次采样,特定业务场景自定义采样等。下图展示了阿里云 ARMS 自定义采样配置页面,用户可以根据自身需要自由定制存储策略,实际存储成本通常小于原始数据的 5%。
链路路分析的约束条件
链路分析虽然使用起来非常灵活,可以满足不同场景的自定义诊断需求。但是它也有几点使用约束限制:
- 基于链路明细数据进行分析的成本较高。 链路分析的前提是尽可能完整的上报并存储链路明细数据,如果采样率比较低导致明细数据不全,链路分析的效果就会大打折扣。为了降低全量存储成本,可以在用户集群内部署边缘数据节点,进行临时数据缓存与处理,降低跨网络上报开销。或者,在服务端进行冷热数据分离存储,热存储进行全量链路分析,冷存储进行错慢链路诊断。
- 后聚合分析的查询性能开销大,并发小,不适合用于告警。 链路分析是实时的进行全量数据扫描与统计,查询性能开销要远大于预聚合统计指标,所以不适合进行高并发的告警查询。需要结合自定义指标功能将后聚合分析语句下推至客户端进行自定义指标统计,以便支持告警与大盘定制。
- 结合自定义标签埋点,才能最大化释放链路分析价值。 链路分析不同于标准的应用监控预聚合指标,很多自定义场景的标签需要用户手动埋点打标,这样才能最有效的区分不同业务场景,实现精准分析。
经典链路告警规则
经典链路告警规则包括核心接口的黄金三指标告警:
- 流量下跌、
- 响应变慢、
- 错误率上升。
此外,异常调用次数增多、慢 SQL 与缓存命中率下跌也是比较重要的链路告警规则,可以默认启用。
采样
业界常用的方法主要分为头部采样(Head-based Sampling)和尾部采样(Tail-based Sampling)两种。头部采样一般在客户端 Agent 等边缘节点进行,例如根据接口服务进行限流采样或固定比例采样;而尾部采样通常基于全量热数据进行过滤,如错慢全采等。
最理想的采样策略应该只存储真正需要查询的数据,APM 产品需要提供灵活的采样策略配置能力与最佳实践,用户结合自身业务场景进行自适应的调整。
全链路追踪的价值
完整的全链路追踪可以为业务带来三大核心价值:端到端问题诊断,系统间依赖梳理,自定义标记透传。
- 端到端问题诊断: VIP 客户下单失败,内测用户请求超时,许多终端用户的体验问题,追根溯源就是由于后端应用或云端组件异常导致的。而全链路追踪是解决端到端问题最有效的手段,没有之一。
- 系统间依赖梳理: 新业务上线,老业务裁撤,机房搬迁/架构升级,IT 系统间的依赖关系错综复杂,已经超出了人工梳理的能力范畴,基于全链路追踪的拓扑发现,使得上述场景决策更加敏捷、可信。
- 自定义标记透传: 全链路压测,用户级灰度,订单追溯,流量隔离。基于自定义标记的分级处理&数据关联,已经衍生出了一个繁荣的全链路生态。然而,一旦发生数据断链、标记丢失,也将引发不可预知的逻辑灾难。
背景
Dapper论文中对实现一个分布式跟踪系统提出了如下几个需求:
- 性能低损耗:分布式跟踪系统对服务的性能损耗应尽可能做到可以忽略不计,尤其是对性能敏感的应用不能产生损耗
- 对应用透明:即要求尽可能用非侵入的方式来实现跟踪,尽可能做到业务代码的低侵入,对业务开发人员应该做到透明化
- 可伸缩性:高伸缩性是指不能随着微服务和集群规模的扩大而使分布式跟踪系统瘫痪
- 跟踪数据可视化和迅速反馈:即要有可视化的监控界面,从跟踪数据收集、处理到结果的展现尽量做到快速,就可以对系统的异常状况作出快速的反应
- 持续的监控:即要求分布式跟踪系统必须是7x24小时工作的,否则将难以定位到系统偶尔抖动的行为
“两类风险”与“十大典型问题”
线上应用风险主要分为“错”、“慢”两大类。其中 “错”的原因通常是程序运行不符合预期, 比如 JVM 加载了错误版本的类实例,代码进入异常分支,环境配置错误等。而 “慢”的原因通常是资源不足,比如突发流量导致 CPU 打满,微服务或数据库线程池被耗尽,内存泄漏导致持续 FGC 等等。
无论是“错”问题,还是“慢”问题。从用户的角度,都是希望能够快速定位根因,及时止损,并消除隐患。但是,根据作者五年多的 Trace 开发、运维与双十一大促备战经验来看,绝大部分线上问题是无法仅通过链路追踪的基础能力就能够有效定位并解决的。 线上系统的复杂性决定了一款优秀的 Trace 产品必须提供更加全面、有效的数据诊断能力,比如代码级诊断、内存分析、线程池分析等;同时,为了提高 Trace 组件的易用性和稳定性,还需要提供动态采样、无损统计、接口名称自动收敛等能力。这也是为什么业界主流 Trace 产品都在逐步向 APM、应用可观测领域升级。为了方便理解,本文仍然以 Trace 来统一表述应用层的可观测能力。
综上所述,线上应用为了保障最终的业务稳定性,在做链路追踪方案选型时,除了 Trace 通用基础能力外(如调用链、服务监控、链路拓扑),还可以参考下面列举的“十大典型问题”(以 Java 应用为例),综合对比开源自建、开源托管与商业化自研 Trace 产品的差异化表现。