Uber 工程团队在 LinkedIn 上抛出一个问题:当一个请求失败,你怎么判断真正的原因是什么?在 Uber 的体量下,这件事会迅速变复杂——数千个服务和依赖相互交织,传统追踪未必能及时给出全貌。
![]()
为此,Uber 开发了一套自动化方法,用来绘制服务依赖关系,并分类下游故障在其服务网格中如何传播。系统通过 RPC 中间件,把生产请求中的调用方与被调用方故障关联起来,将依赖划分为 fail-close、fail-open 或 unknown 三类。Uber 表示,这套方法已经为关键 API 编目了依赖关系,并索引了服务网格中大多数 fail-close 异常。
在微服务架构里,请求可能穿过深层嵌套和异步的服务调用,判断哪个依赖导致了故障并不容易。Uber 对 fail-close 依赖的定义是:它的失败会持续导致调用方失败。fail-open 依赖则可以在不导致调用方失败的情况下失败,而证据不足时归为 unknown。这些分类随后可以沿调用路径应用,识别故障如何向发起请求的 API 传播。
Uber 最初考虑用分布式追踪来建立这些关系,但发现采样对于罕见故障来说太慢。公司称,超过 99.9% 的请求在可接受的延迟范围内无错误完成。在 0.01% 的采样率和 99.9% 的可用性下,一个出错请求被采样的概率是千万分之一。按每秒 500 个请求计算,捕获一个失败请求可能需要 5 小时 33 分 20 秒。
Uber 工程师 Deepanshu Mehndiratta、Alok Srivastava 和 Shivam Jindal 将这一方法描述为在单个请求可见性与更快的依赖分析之间做权衡。他们表示:“我们需要更快的反馈,所以开始通过日志来识别依赖。”
Uber 的服务间请求经由 Muttley 路由,这是用于路由和遥测的驻主机代理。但 Muttley 缺少调用方端点上下文,无法做精确的依赖关联。Uber 把分析加到了 YARPC——其面向 Go 和 Java 的 RPC 框架——通过入站和出站中间件实现。
入站中间件生成请求 ID,并在内存中的 RequestTracker 记录调用方服务和端点。该 ID 通过 Go 的 context 传播,使出站中间件能够记录下游服务、端点和调用结果。请求完成时,中间件发出指标,捕获调用方和被调用方的失败状态。
Uber 根据观测到的调用方与被调用方结果,为每个调用方依赖计算失败相关概率。数值 ≥0.8 归为 fail-close,≤0.2 归为 fail-open,中间值归为 unknown。重试被单独处理,以免被当作独立依赖。
与基于 OpenTelemetry 构建的分布式追踪管线不同——后者可以用尾部采样根据错误或延迟保留追踪——Uber 使用中间件指标来捕获生产故障,无需存储和评估单条追踪的开销,用请求级细节换取更广的覆盖范围。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.