首頁  >  文章  >  web前端  >  剖析Node.js cluster模組使用詳解

剖析Node.js cluster模組使用詳解

php中世界最好的语言
php中世界最好的语言原創
2018-05-24 09:52:151527瀏覽

這次帶給大家剖析Node.js cluster模組使用詳解,Node.js cluster模組使用詳解的注意事項有哪些,下面就是實戰案例,一起來看一下。

cluster模組概覽

node實例是單執行緒作業的。在服務端程式設計中,通常會建立多個node實例來處理客戶端的請求,以此提升系統的吞吐率。對這樣多個node實例,我們稱之為cluster(叢集)。

借助node的cluster模組,開發者可以在幾乎不修改原有專案程式碼的前提下,獲得叢集服務帶來的好處。

叢集有以下兩種常見的實作方案,而node自帶的cluster模組,採用了方案二。

方案一:多個node實例多個端口

集群內的node實例,各自監聽不同的端口,再由反向代理實現請求到多個連接埠的分發。

  1. 優點:實作簡單,各實例相對獨立,這對服務穩定性有好處。

  2. 缺點:增加連接埠佔用,進程之間通訊比較麻煩。

方案二:主程序向子程序轉送請求

群集內,建立一個主程序(master),以及若干個子程序( worker)。由master監聽客戶端連線請求,並依照特定的策略,轉送給worker。

  1. 優點:通常只佔用一個端口,通訊相對簡單,轉送策略更靈活。

  2. 缺點:實作相對複雜,對主流程的穩定性要求較高。

入門實例

#在cluster模組中,主程式稱為master,子程式稱為worker。

範例如下,建立與CPU數目相同的服務端實例,來處理客戶端請求。注意,它們監聽的都是同樣的連接埠。

// server.js
var cluster = require('cluster');
var cpuNums = require('os').cpus().length;
var http = require('http');
if(cluster.isMaster){
 for(var i = 0; i < cpuNums; i++){
  cluster.fork();
 }
}else{
 http.createServer(function(req, res){
  res.end(`response from worker ${process.pid}`);
 }).listen(3000);
 console.log(`Worker ${process.pid} started`);
}

建立批次腳本:./req.sh。

#!/bin/bash
# req.sh
for((i=1;i<=4;i++)); do  
 curl http://127.0.0.1:3000
 echo ""
done

輸出如下。可以看到,響應來自不同的進程。

response from worker 23735
response from worker 23731
response from worker 23729
response from worker 23730

cluster模組實作原理

了解cluster模組,主要搞清楚3個問題:

  1. master、worker如何通訊?

  2. 多個server實例,如何實作連接埠共用?

  3. 多個server實例,來自客戶端的請求如何分發到多個worker?

下面會結合示意圖介紹,原始碼層級的介紹,可以參考 筆者的github。

問題1:master、worker如何通訊

這個問題比較簡單。 master程序透過 cluster.fork() 來建立 worker進程。 cluster.fork() 內部 是透過 child_process.fork() 來建立子程序。

也就是說:

  1. master行程、worker行程是父、子行程的關係。

  2. master進程、woker進程可以透過IPC通道進行通訊。 (重要)

問題2:如何實作連接埠共用

在前面的範例中,多個woker中建立的server監聽了同個連接埠3000。通常來說,多個進程監聽同個端口,系統會報錯。

為什麼我們的例子沒問題呢?

秘訣在於,net模組中,對 listen() 方法進行了特殊處理。根據目前進程是master進程,還是worker進程:

  1. master進程:在該連接埠上正常監聽請求。 (沒做特殊處理)

  2. worker进程:创建server实例。然后通过IPC通道,向master进程发送消息,让master进程也创建 server 实例,并在该端口上监听请求。当请求进来时,master进程将请求转发给worker进程的server实例。

归纳起来,就是:master进程监听特定端口,并将客户请求转发给worker进程。

如下图所示:

问题3:如何将请求分发到多个worker

每当worker进程创建server实例来监听请求,都会通过IPC通道,在master上进行注册。当客户端请求到达,master会负责将请求转发给对应的worker。

具体转发给哪个worker?这是由转发策略决定的。可以通过环境变量NODE_CLUSTER_SCHED_POLICY设置,也可以在cluster.setupMaster(options)时传入。

默认的转发策略是轮询(SCHED_RR)。

当有客户请求到达,master会轮询一遍worker列表,找到第一个空闲的worker,然后将该请求转发给该worker。

master、worker内部通信小技巧

在开发过程中,我们会通过 process.on('message', fn) 来实现进程间通信。

前面提到,master进程、worker进程在server实例的创建过程中,也是通过IPC通道进行通信的。那会不会对我们的开发造成干扰呢?比如,收到一堆其实并不需要关心的消息?

答案肯定是不会?那么是怎么做到的呢?

当发送的消息包含cmd字段,且改字段以NODE_作为前缀,则该消息会被视为内部保留的消息,不会通过message事件抛出,但可以通过监听'internalMessage'捕获。

以worker进程通知master进程创建server实例为例子。worker伪代码如下:

// woker进程
const message = {
 cmd: 'NODE_CLUSTER',
 act: 'queryServer'
};
process.send(message);

master伪代码如下:

worker.process.on('internalMessage', fn);

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

设计模式的策略模式怎样在前端中使用

如何对微信小程序进行开发

以上是剖析Node.js cluster模組使用詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn