首頁  >  文章  >  web前端  >  Node.js中cluster模組的介紹

Node.js中cluster模組的介紹

不言
不言原創
2018-07-04 11:20:271202瀏覽

這篇文章主要介紹了Node.js中cluster模組的介紹,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

Node的單線程設計已經沒法更充分的"壓榨"機器性能了,Node新增了一個內置模組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: &#39;NODE_CLUSTER&#39;,
 act: &#39;queryServer&#39;
};
process.send(message);

master伪代码如下:

worker.process.on(&#39;internalMessage&#39;, fn);

相关链接

官方文档:https://nodejs.org/api/cluster.html

Node学习笔记:https://github.com/chyingp/nodejs-learning-guide

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

nodejs中实现路由功能的方法

对于Nodejs的Http模块的解析

nodejs中模块定义的介绍

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

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