async_hooks
模块是Node.js 8.0中增加的特性,旨在帮助开发者追踪 Node.js 创建的异步调用资源的生命周期情况。目前此模块还处于 Experimental
阶段,不建议用于线上,不过在我们开发时会大有帮助。
Async Hooks 使用
async_hooks
的 api 很简单,使用 async_hooks.createHook(callbacks)
即可创建 init
、 before
、 after
、 destory
四个阶段的钩子回调函数。
通过以上代码,我们创建了一个可以跟踪所有异步代码的实例,默认情况下,需执行 .enable()
方法来开启对异步资源的监听。
init
回调
当异步资源被构造时,会触发 init
回调。
init
回调共有四个参数:
-
asyncId
唯一的资源 ID。如果你在使用Node.js 10.x的Worker
,每个线程的资源 ID 都是相互独立的。 -
type
用于标识异步资源,Node.js内置的异步调用包括Promise
都会有一个唯一的type
,同时用户也可通过 API 去自定义type
。 -
triggerAsyncId
用于标识当前异步资源的调用者。 -
resource
asyncId
引用的资源。init
被触发时,可能还未初始化完成,resource
可能无法使用
在上面代码中,假如用 console.log()
或者 process.stdout
输出,因这二者为异步操作,会导致AsyncHooks被无限调用。
运行上述代码并使用 nc localhost 8080
访问服务器三次后得到如下:
在结果中:
-
TCPSERVERWRAP
表示我们创建的 TCP 服务器 -
TickObject
表示process.nextTick()
,在我们代码中.listen()
为异步操作,调用了process.nextTick()
-
TCPWRAP
表示来自客户端的连接
async_hooks.executionAsyncId()
返回当前作用域的异步资源 id,代码执行时 id 从 1 开始增加。我们通过 triggerAsyncId
和 executionAsyncId
可以确定代码调用和执行顺序:
-
程序运行时创建TCP服务器实例
-
-> 实例监听8080端口
-
-> 客户端连接当前 TCP 服务器
-
-> 客户端连接当前 TCP 服务器
-
....
-
-> 客户端连接当前 TCP 服务器
TCPWRAP
的 executionAsyncId
为0,表示此资源并非来自 JS 栈,而是由C++代码创建的。每一次的 triggerAsyncId
都相同,表示每次请求都访问的是相同的 TCP 服务器实例,我们可以根据这一特性去监控 TCP 连接情况。
before
回调
当异步操作初始化或完成后,在调用回调函数之前,将触发 before
回调。使用场景不同, before
回调调用次数也不尽相同,如 TCP 请求场景中会回调多次,文件操作 fs.open()
仅调用一次。
after
回调
回调函数执行之后会立即触发 after
回调。如异步回调执行过程中有错误产生, after
回调会在 uncaughtException
事件触发之后执行。
destory
回调
异步资源销毁,如客户端断开连接时,或 asyncResource.emitDestroy()
调用时将触发 destory
回调。
AsyncResource
默认情况下只有系统级别的异步操作才能被钩子回调追踪到,不过Node.js也为我们提供了追踪自定义的异步资源的能力。
triggerAsyncId
指定调用者资源 id,默认为当前作用域资源id。
asyncResource.runInAsyncScope(fn[, thisArg, ...args])
会顺序触发 init
回调、调用 fn、触发 after
回调。
asyncResource.emitDestroy()
触发 destory
回调,仅能被调用一次。当资源被触发 GC 前未执行 destory
,GC 后 destory
将不再被触发,这时候容易产生内存泄露。
Async Hooks 实战
Node.js中异步代码的错误栈信息“短小且不精悍”,追踪错误时很容易让人抓狂。Async Hooks为我们提供了无侵入的处理方式。
在上面的代码中,在 init
阶段通过记录当前上下文档栈信息, uncaughtException
事件被触发时,打印额外的错误信息,并标记当前执行结果异常,我们可以在随后的 after
阶段执行如错误上报等操作。
执行结果如图:
可以看到,我们丰富了错误栈信息,并且清晰的展示了异步资源的执行情况。
小结
在 Async Hooks 出现之前,社区中也出现过类似的模块,Async Hooks 可看作这些模块的官方的支持。为了支持 Async Hooks,官方在代码中增加了很多钩子回调当调用,有兴趣可以看看提交记录,也更方便我们理解 Async Hooks。
对于开发者,我们可以用 Async Hooks 无侵入的特性监控、调试我们的代码,现在社区也出现了利用此特性的应用管理器,对开发者着实是方便不少。
参考资料
-
Async Hooks
-
Node.js v8.x 新特性 Async Hook 简介
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。