菜单

日志的事务ID

相关源文件

目的与范围

本文档描述了在 Node.js 应用程序中为日志关联实现和使用事务 ID。事务 ID 作为唯一标识符,将跨请求流的相关日志条目连接起来,使开发人员能够跟踪和调试操作,即使在复杂的分布式系统中也是如此。有关更广泛的日志记录策略,请参阅监控与可观测性

什么是事务 ID?

事务 ID(有时也称为关联 ID)是分配给进入系统的每个请求的唯一标识符。此标识符贯穿请求的整个生命周期,出现在与该请求相关的所有日志条目中,无论是由哪个服务、组件或函数生成这些日志。

在典型的 Node.js 应用程序中,尤其是在微服务架构中,单个用户请求可能会触发跨多个服务的数十个操作。如果没有事务 ID,调查问题将变得极其困难,因为来自相关操作的日志会散布在不相关的条目中。

来源:sections/production/assigntransactionid.md5-7

事务 ID 的好处

事务 ID 提供了几个关键的好处

  1. 请求跟踪:跟踪单个请求贯穿所有系统组件
  2. 调试效率:快速过滤日志,仅关注相关条目
  3. 跨服务关联:连接微服务之间的相关操作
  4. 可观测性增强:提高对请求路径和失败的可见性

带事务 ID 和不带事务 ID 的日志的视觉比较

带事务 ID不带事务 ID
每个条目都包含一个通用标识符无法自动关联条目
可以过滤日志以仅查看一个事务必须手动解析并连接相关日志
系统中的清晰路径可见难以遵循执行流程
高效的故障排除耗时的调查

来源:sections/production/assigntransactionid.md185-190

事务 ID 实现方法

在 Node.js 应用程序中实现事务 ID 有几种方法,推荐的方法取决于您的 Node.js 版本和性能考虑。

实现架构

下图展示了 Express 应用程序中事务 ID 实现的通用架构

来源:sections/production/assigntransactionid.md11-76

现代方法:使用 AsyncLocalStorage

对于 Node.js v14 及更高版本,AsyncLocalStorage 为在异步操作中维护上下文提供了最健壮的解决方案。

关键组件

  • 来自 async_hooks 模块的 AsyncLocalStorage
  • 初始化上下文和事务 ID 的中间件
  • 从存储中检索 ID 的日志记录器

实施流程

  1. 创建初始化 AsyncLocalStorage 的中间件
  2. 从请求中生成或提取事务 ID
  3. 将 ID 存储在 AsyncLocalStorage 中
  4. 从请求生命周期的任何点访问 ID
  5. 通过 HTTP 标头将 ID 传递给外部服务

来源:sections/production/assigntransactionid.md11-76 sections/production/assigntransactionid.md145-148

辅助库:cls-rtracer

为了简化语法并与流行框架集成,可以使用 cls-rtracer 等库。这些库提供特定于框架的中间件/插件,并带有合理的默认设置。

优点

  • 更简单的 API
  • 内置支持流行框架
  • 自动进行服务到服务通信的标头管理

来源:sections/production/assigntransactionid.md79-142

遗留方法:continuation-local-storage

对于较旧的 Node.js 版本,continuation-local-storage 提供了类似的功能,但存在一些限制。

来源:sections/production/assigntransactionid.md151-180

跨服务事务 ID 传播

事务 ID 的关键方面是在服务边界之间维护它们。这使得能够对跨越多个服务的请求进行端到端跟踪。

HTTP 标头传播

标准方法是通过 HTTP 标头传递事务 ID

  1. 在传出的请求中包含事务 ID,并使用标头(通常是 x-transaction-id
  2. 在下游服务中提取传入请求中的 ID
  3. 如果缺失,则使用提取的 ID 或生成新 ID

cls-rtracer 这样的库提供了配置选项来自动处理此传播

来源:sections/production/assigntransactionid.md127-141

日志集成

为了充分利用事务 ID,您的日志记录系统必须在每个日志条目中包含该 ID。

日志记录器实现

日志记录器应从适当的存储机制检索事务 ID,并将其包含在所有日志消息中

使用 AsyncLocalStorage

使用 cls-rtracer

来源:sections/production/assigntransactionid.md66-75 sections/production/assigntransactionid.md111-120

最佳实践和注意事项

实施建议

  1. 对较新的 Node.js 版本使用 AsyncLocalStorage - 它为维护上下文提供了更强大的解决方案
  2. 考虑使用辅助库 - 它们在保持功能的同时简化了实现
  3. 标准化标头名称 - 在服务之间使用一致的标头名称(例如,x-transaction-id
  4. 生成 UUID - 使用 UUID 或类似的唯一标识符来防止冲突
  5. 尽早设置 ID - 在请求处理链中,最好在中间件中设置
  6. 在所有日志中包含 ID - 将其作为所有日志操作的标准实践

性能考量

  • AsyncLocalStorage 基于 async_hooks,在 Node.js 中技术上仍处于实验阶段
  • 性能影响通常可以忽略不计,但应为高吞吐量应用程序考虑
  • 改进调试和可观测性的好处通常 outweigh 较小的性能开销

来源:sections/production/assigntransactionid.md145-148

总结

事务 ID 是增强 Node.js 应用程序可观测性和可调试性的强大工具,尤其是在分布式系统中。通过实现事务 ID 系统,您可以有效地跟踪请求流,跨服务关联日志,并显着提高在生产环境中对问题进行故障排除的能力。

正如行业专家所指出的:“关联 ID 的概念很简单。它是在给定事务中所有请求、消息和响应的通用值。有了这种简单性,您就获得了巨大的力量。”

来源:sections/production/assigntransactionid.md194-198