乐趣区

关于javascript:Nodejs-如何实现异步资源上下文共享

大家好,我是晚天。

接下来,应用尽量简略的形式介绍 Node.js 如何实现异步资源上下文共享,以及异步资源上下文共享对咱们来说有什么用。

异步资源上下文共享,象征在一次网络申请生命周期或异步资源调用链中共享上下文数据。

答复这个问题之前,首先咱们要先了解什么是异步资源。

异步资源

异步资源能够了解为是有回调的对象,比方但不限于 Promises、Timeouts、TCPWrap、UDP 等。详见异步资源的类型列表。

官网定义如下:

An asynchronous resource represents an object with an associated callback. This callback may be called multiple times, such as the ‘connection’ event in net.createServer(), or just a single time like in fs.open(). A resource can also be closed before the callback is called.

AsyncLocalStorage

这里介绍 Node.js 官网提供的异步上下文共享计划 AsyncLocalStorage,该个性在 16.4.0 之前还是试验个性,16.4.0 之后曾经稳固。

AsyncLocalStorage 能够在异步操作链中共享数据。

AsyncLocalStorage 实例 asyncLocalStorage 有以下几个次要办法:

  • disable() 禁用 asyncLocalStorage;
  • getStore() 返回以后上下文 store,该 store 须通过 asyncLocalStorage.run() 或 asyncLocalStorage.enterWith() 来进行异步上下文初始化;
  • enterWith(store) 通过该办法传入上下文 store,在后续所有的异步调用中均能够获取该 store;

示例:

const store = {id: 1};
// Replaces previous store with the given store object
asyncLocalStorage.enterWith(store);
asyncLocalStorage.getStore(); // Returns the store object
someAsyncOperation(() => {asyncLocalStorage.getStore(); // Returns the same object
});
  • run(store, callback[, …args]) 通过 run 来指定上下文 store 和其失效的 callback 函数,该 store 将只能在该 callback 函数中被获取到。
  • exit(callback[, …args])

asyncLocalStorage.run() 函数第一个参数是存储咱们在异步调用中所须要拜访的共享数据,第二个参数是一个异步函数。

上面通过一个例子来演示如何应用 AsyncLocalStorage 来实现异步资源上下文共享:

输入:

runA 8f19ebef-58d7-4b1a-8b9b-46d158beb5d2 2022/5/24 20:26:17 this is a log message
runB 8f19ebef-58d7-4b1a-8b9b-46d158beb5d2 2022/5/24 20:26:17 this is a log message

通过 asyncLocalStorage.run 运行的同一个异步函数中,会运行函数 runA 和函数 runB,runA 和 runB 能够拜访到雷同的上下文数据。

性能问题

AsyncLocalStorage 为咱们在 Node.js 中轻松实现异步资源上下文共享提供了很大遍历,然而每次异步资源操作都会触发 Async Hooks,势必会对咱们的 Node 利用性能造成肯定影响。那么影响到底有多大呢?

依据 Kuzzle 的一个实测,应用 AsyncLocalStorage 大略会造成 8% 的额定性能损耗,当然不同的业务场景可能会有不同的性能体现。如果大家关注这部分性能体现,也能够在本人的业务中减少比照测试,测试具体性能影响。

—- Log with AsyncLocalStorage Log classic difference
req/s 2613 2842 〜8%

利用场景

在其余多线程语言中,每个 HTTP 创立一个新的线程,每个线程领有本人的内存。你能够在在线程内存中存储全局状态,并在代码的任何地位获取到全局状态。

在 Node.js 中,因为 Node.js 是单线程的,会在所有 HTTP 申请中共享内存,所以每个 HTTP 申请无奈做到持有互相隔离的全局状态。

AsyncLocalStorage 能够无效隔离不同异步操作之间的状态,在 HTTP 申请追踪、APM 工具、上下文日志追踪、基于申请的全链路日志追踪等场景有十分重要的作用。

参考资料

  • AsyncLocalStorage Docs
  • Simple Context Passing With AsyncLocalStorage in Node.js
  • Node AsyncLocalStorage shares status with asynchronous resources
  • Async local storage
  • 应用 Node.js 的 Async Hooks 模块追踪异步资源
  • Using Async Hooks for Request Context Handling in Node.js
  • Getting per-request context in NodeJS with async_hooks
  • Async Hooks: A Journey To a Realm With Persistent Execution Context | Node.TLV 20
  • Node AsyncLocalStorage shares status with asynchronous resources
  • In Node.js Using async hooks to handle HTTP request context in
退出移动版