本文档描述了在 Node.js 应用程序中为日志关联实现和使用事务 ID。事务 ID 作为唯一标识符,将跨请求流的相关日志条目连接起来,使开发人员能够跟踪和调试操作,即使在复杂的分布式系统中也是如此。有关更广泛的日志记录策略,请参阅监控与可观测性。
事务 ID(有时也称为关联 ID)是分配给进入系统的每个请求的唯一标识符。此标识符贯穿请求的整个生命周期,出现在与该请求相关的所有日志条目中,无论是由哪个服务、组件或函数生成这些日志。
在典型的 Node.js 应用程序中,尤其是在微服务架构中,单个用户请求可能会触发跨多个服务的数十个操作。如果没有事务 ID,调查问题将变得极其困难,因为来自相关操作的日志会散布在不相关的条目中。
来源:sections/production/assigntransactionid.md5-7
事务 ID 提供了几个关键的好处
带事务 ID 和不带事务 ID 的日志的视觉比较
| 带事务 ID | 不带事务 ID |
|---|---|
| 每个条目都包含一个通用标识符 | 无法自动关联条目 |
| 可以过滤日志以仅查看一个事务 | 必须手动解析并连接相关日志 |
| 系统中的清晰路径可见 | 难以遵循执行流程 |
| 高效的故障排除 | 耗时的调查 |
来源:sections/production/assigntransactionid.md185-190
在 Node.js 应用程序中实现事务 ID 有几种方法,推荐的方法取决于您的 Node.js 版本和性能考虑。
下图展示了 Express 应用程序中事务 ID 实现的通用架构
来源:sections/production/assigntransactionid.md11-76
对于 Node.js v14 及更高版本,AsyncLocalStorage 为在异步操作中维护上下文提供了最健壮的解决方案。
关键组件
async_hooks 模块的 AsyncLocalStorage实施流程
来源:sections/production/assigntransactionid.md11-76 sections/production/assigntransactionid.md145-148
为了简化语法并与流行框架集成,可以使用 cls-rtracer 等库。这些库提供特定于框架的中间件/插件,并带有合理的默认设置。
优点
来源:sections/production/assigntransactionid.md79-142
对于较旧的 Node.js 版本,continuation-local-storage 提供了类似的功能,但存在一些限制。
来源:sections/production/assigntransactionid.md151-180
事务 ID 的关键方面是在服务边界之间维护它们。这使得能够对跨越多个服务的请求进行端到端跟踪。
标准方法是通过 HTTP 标头传递事务 ID
x-transaction-id)像 cls-rtracer 这样的库提供了配置选项来自动处理此传播
来源:sections/production/assigntransactionid.md127-141
为了充分利用事务 ID,您的日志记录系统必须在每个日志条目中包含该 ID。
日志记录器应从适当的存储机制检索事务 ID,并将其包含在所有日志消息中
使用 AsyncLocalStorage
使用 cls-rtracer
来源:sections/production/assigntransactionid.md66-75 sections/production/assigntransactionid.md111-120
x-transaction-id)来源:sections/production/assigntransactionid.md145-148
事务 ID 是增强 Node.js 应用程序可观测性和可调试性的强大工具,尤其是在分布式系统中。通过实现事务 ID 系统,您可以有效地跟踪请求流,跨服务关联日志,并显着提高在生产环境中对问题进行故障排除的能力。
正如行业专家所指出的:“关联 ID 的概念很简单。它是在给定事务中所有请求、消息和响应的通用值。有了这种简单性,您就获得了巨大的力量。”