
上周,发布了Node.js版本10.5.0,其中包含一项创新,其重要性几乎不可被高估-以worker_threads模块的形式提供多线程支持。 我会立即提出保留意见,该API处于实验阶段,因此可能会有所变化,但是现在您可以对它印象深刻,并了解其基础中所包含的原理和技术。 如果您有需求,请参与完成接口,编写代码或修复错误( 问题清单)。
外观故事
在整个Node.js生命周期中,并行化计算的唯一方法是启动一个新进程,例如,使用集群模块。 由于多种原因,这种方法不适合开发人员,尤其是因为它导致将所有内置模块的Node.js可执行代码重复加载到计算机内存中,这是一种浪费资源的低效方式。
尽管如此,关于Node.js中多线程实现的讨论始终基于V8的复杂性和众多未知因素:如何连接本机模块,共享内存,线程之间进行通信等等。 当开发人员在寻找在网络上解决该问题的一方时, Worker API已成功实现,在最初阶段便成为指南。 开发以addaleax开始,并已被社区接管。
在这一年中进行了积极的工作,在此期间指定了设计要求,并且API获得了自己的特定于Node.js的功能,并且该模块本身称为worker_threads。 下面,我将简要概括地描述worker_threads,并进行详细研究,建议您访问官方文档页面。
内容描述
如上所述,此开发的目标是通过在同一进程中的各个线程之间分配负载,而不是启动多个进程来提高生产率。 因此,线程将支持主进程可用的所有模块的连接(当前不支持本机模块)。
与在Worker API中一样,主流和子流之间的交互是通过postMessage传输Transferrable对象来进行的,这避免了同时访问的问题,尽管它需要额外的内存访问来复制数据。 在这种情况下,诸如SharedArrayBuffer之类的对象将保留其行为,并且不会导致重新分配。
MessageChannel和MessagePort取自WebAPI ,它使您可以创建隔离的消息传递通道并在线程之间传输它们。
为了尝试使用worker_threads,在启动进程时,必须指定一个特殊标志:
node --experimental-worker main.js
例子
由于API可能仍会更改,因此我将不对其进行描述,但我将举一个父子线程之间的消息交换示例,其中子线程通过MessagePort报告其threadId并退出。
主流
主线程的示例代码:
子流
子线程一直存在,直到其事件循环为空。 因此, worker.js
来自worker.js
的代码后worker.js
线程将立即自动关闭。 为了与父级通信,使用parentPort:
在子线程中,流程对象被覆盖,并且其行为与父线程中的流程行为略有不同。 特别是,没有办法响应SIGNINT信号,更改process.env
的值以及调用process.exit
只会停止worker,而不会停止整个过程。
结论
工作人员将大大简化需要并行可执行代码段之间进行交互的应用程序的创建,这一点尤其重要,它使通信和流控制成为最明显的方式。 而且还可以避免Windows和Unix之间的差异引起的特定于平台的限制。 我确信,将打开的机会将吸引尚未选择Node.js的新开发人员。 同时,继续监视更改并连接到存储库中的API开发过程。
参考文献