盒子
盒子
文章目录
  1. Node的多进程和多线程问题
    1. 开启多进程
    2. 进程之间的通信
    3. 开启多线程
    4. 总结

Node开启多线程多进程

Node的多进程和多线程问题

我们知道Node.js是以单线程的模式运行的,但它使用的是事件驱动来处理并发,这样有助于我们在多核cpu的系统上创建多个进程,从而提高性能。

面试官:问你Node能开启多线程吗?

你:No problem!

开启多进程

node中开启多进程有两个模块:child_process模块的cluster模块。

child_process模块可以实现子进程,从而实现广义的多进程模式。

child_process模块中提供了四个创建子进程的方法,区别如下:

  • spawn:子进程中执行的是非node程序,提供一组参数后,执行的结果以流的形式返回
  • execFile:子进程中执行的是非node程序,提供一组参数后,执行的结果以回调的形式返回
  • exec:子进程中执行的是非node程序,提供一组shell命令,执行的结果以回调的形式返回
  • fork:子进程中执行的是node程序,提供一组参数后,执行的结果以流的形式返回

node中的主进程称为Master线程,子进程称为Worker进程。在创建子进程之后,父子进程就可以开始进行通信。

单个Node.js实例运行在单个线程中。为了充分利用多核系统,有时候需要启用一组Node.js进程去处理负载任务。

cluster模块可以创建共享服务器端口的子进程。

工作进程由child_process.fork()方法创建,因此它们可以使用IPC和父进程通信,从而使各进程交替处理连接服务。

进程之间的通信

在NodeJS中,父子进程之间的通信可以通过on('message')send()方法实现通信。on('nessage')用来监听message事件,使用send()向其他进程发送消息。

面试官:多个进程可以监听同一个端口吗

主进程和worker可以监听同一个端口,但是master进程是不会处理具体业务的,因此需要使用worker去处理事务。当网络请求到来的时候,会进行抢占式调度。最后只会有一个master抢到任务并且处理。

除了父子进程之间的通信,还有别的通信方式。大概有如下几种:

  • stdin/stdout传递json。是最直接的方式,适用于关联进程之间的通信,无法跨机器。
  • node原生IPC。同样的约束。
  • 通过sockets。这是最通用的方式,有良好的跨环境能力,但存在网络性能消耗的问题。
  • 借助message queue。是为通信问题而扩展出的一层强大的消息中间件。

开启多线程

worker_threads模块允许使用并行地执行JavaScript的线程。

worker_threads相对于I/O密集型操作是没有太大的帮助的,因为异步的I/O操作比worker线程更有效率,但对于CPU密集型操作的性能会提升很大。

线程间的通信方式有:

  • 共享内存。线程之间可以共享内存,使用ArrayBufferSharedArrayBuffer
  • parentPort。主要用于父子线程通信,通过经典的on('message'),postMessage形式。
  • MessageChannel。创建自定义的消息传递通道。

Web 工作线程cluster 模块一样,可以通过线程间的消息传递来实现双向通信。 在内部,一个 Worker 具有一对内置的 MessagePort,在创建该 Worker 时它们已经相互关联。 虽然父端的 MessagePort 对象没有直接公开,但其功能是通过父线程的 Worker 对象上的 worker.postMessage()worker.on('message') 事件公开的。

要创建自定义的消息传递通道(建议使用默认的全局通道,因为这样可以促进关联点的分离),用户可以在任一线程上创建一个 MessageChannel 对象,并将该 MessageChannel 上的 MessagePort 中的一个通过预先存在的通道传给另一个线程,例如全局的通道。

总结

  • 开启多进程使用child_process模块或cluster模块,开启多线程使用worker_threads模块
  • 进程创建有四个方法spawnexecexecFilefork
  • 进程通信方式有stdin/stdout传递jsonnode原生IPCsocketsmessage queue
  • 线程通信方式共享内存、parentPortMessageChannel

个人微信公众号

支持一下
扫码关注我的微信公众号-大前端合集
  • 微信公众号-大前端合集