您好,登錄后才能下訂單哦!
node中cluster集群的作用是什么?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
結論
雖然平常通過設置為CPU進程數的工作進程,但是可以超過這個數,并且并不是主進程先創建
if (cluster.isMaster) { // 循環 fork 任務 CPU i5-7300HQ 四核四進程 for (let i = 0; i < 6; i++) { cluster.fork() } console.log(chalk.green(`主進程運行在${process.pid}`)) } else { app.listen(1314) // export app 一個 Koa 服務器的實例 console.log(chalk.green(`子進程運行在${process.pid}`)) } #子進程運行在17768 #子進程運行在5784 #子進程運行在11232 #子進程運行在7904 #主進程運行在12960 #子進程運行在4300 #子進程運行在16056
在主進程中 cluster 表示主進程(用于監聽、發送事件), process 是本身的進程,worker 表示子進程,通過 cluster.workers 獲取
在子進程中 process 表示子進程(用于監聽、發送事件),也可以通過 cluster.worker 表示當前子進程
cluster.worker.process 等價于 process(在子進程中)
主進程子進程相互通信
cluster 用于監聽 process(child) 子進程觸發的各種事件
worker 在主進程中獲取,用于和自身通信。當子進程觸發事件時,會返回當前的 worker 以及相關的信息到主進程相應的事件中
process(parent) 主進程本身的進程實例,在通信過程中基本沒有用到
process(child) 子進程本身的實例,只能在子進程獲取用于監聽自身的事件
可見主進程與子進程通過這樣一個三角關系互相通信,其中 cluster 和 worker 是在主進程中獲取的,process(child) 是子進程。 cluster 通過操作 worker 通知子進程,子進程本身和 cluster 進行通信。為什么要這樣設計呢?因為子進程會有多個,只有通過 worker 才能選擇和哪個進程通信
子進程的調度策略 cluster.schedulingPolicy
調度策略,包括循環計數的 cluster.SCHED_RR,以及由操作系統決定的cluster.SCHED_NONE。 這是一個全局設置,當第一個工作進程被衍生或者調動cluster.setupMaster()時,都將第一時間生效。除Windows外的所有操作系統中,SCHED_RR都是默認設置。只要libuv可以有效地分發IOCP handle,而不會導致嚴重的性能沖擊的話,Windows系統也會更改為SCHED_RR。cluster.schedulingPolicy 可以通過設置NODE_CLUSTER_SCHED_POLICY環境變量來實現。這個環境變量的有效值包括"rr" 和 "none"。
RR 即 Round-Robin 輪詢調度,即每個子進程的獲取的事件的機會是均等的,這是除 windows以外默認的。而 windows 下的調度策略很詭異,見下圖。目前并沒有相關 API 可以設置調度策略的算法,node 只為我們提供了兩個值
進程調度算法.png
測試數據為 1000次 并發請求,重復測試20次,在windows下的表現情況。可見 windows 的調度算法表現的雜亂無章。如果是 RR 算法四條進程的調度應該處于同一橫線上。暫時沒在本地搭建 linux 環境,有條件的同學可以協助測試一波。
cluster的調度算法目前至于系統有關
多進程間的鑒權問題
注意:Node.js不支持路由邏輯。因此在設計應用時,不應該過分依賴內存數據對象(如sessions和login等)。由于各工作進程是獨立的進程,它們可以根據需要隨時關閉或重新生成,而不影響其他進程的正常運行。只要有存活的工作進程,服務器就可以繼續處理連接。如果沒有存活的工作進程,現有連接會丟失,新的連接也會被拒絕。Node.js不會自動管理工作進程的數量,而應該由具體的應用根據實際需要來管理進程池。
文檔中已明確說明了,每一個工作進程都是獨立的,并且互相之間除了能夠進行通信外,沒有辦法共享內存。所以在設計鑒權的時候,有兩種方法
通過共有的主進程存儲鑒權信息,每次前端提交帳號密碼,授權完成后,將 token 發送給主進程,下次前臺查詢時先在主進程獲取授權信息
通過統一的外部 redis 存取
兩種方法看來還是第二種好的不要太多,因此多進程的環境下,應該使用外部數據庫統一存儲 token 信息
進一步的子進程間通信思考
雖然 node 中并沒有直接提供的進程間通訊功能,但是我們可以通過主進程相互協調進程間的通訊功能,需要定義標準的通信格式,例如
interface cmd { type: string from: number to: number msg: any }
這樣通過統一的格式,主進程就可以識別來自各個進程間的通信,起到進程通信中樞的功能
egg.js 中 agent 的實現
+--------+ +-------+ | Master |<-------->| Agent | +--------+ +-------+ ^ ^ ^ / | \ / | \ / | \ v v v +----------+ +----------+ +----------+ | Worker 1 | | Worker 2 | | Worker 3 | +----------+ +----------+ +----------+
我們看到 egg 在多進程模型之間實現了一個 agent 進程,這個進程主要負責對整個系統的定期維護
說到這里,Node.js 多進程方案貌似已經成型,這也是我們早期線上使用的方案。但后來我們發現有些工作其實不需要每個 Worker 都去做,如果都做,一來是浪費資源,更重要的是可能會導致多進程間資源訪問沖突。舉個例子:生產環境的日志文件我們一般會按照日期進行歸檔,在單進程模型下這再簡單不過了:
每天凌晨 0 點,將當前日志文件按照日期進行重命名
銷毀以前的文件句柄,并創建新的日志文件繼續寫入
試想如果現在是 4 個進程來做同樣的事情,是不是就亂套了。所以,對于這一類后臺運行的邏輯,我們希望將它們放到一個單獨的進程上去執行,這個進程就叫 Agent Worker,簡稱 Agent。Agent 好比是 Master 給其他 Worker 請的一個『秘書』,它不對外提供服務,只給 App Worker 打工,專門處理一些公共事務。
這樣我們可以指定一個進程作為 agent 進程,用于實現自己定義的事務。在 egg 中,主線程啟動后 首先 fork agent進程,當 agent 進程啟動完成后再啟動具體的 worker 進程。參照上面的代碼,相信這部分邏輯現在也不難實現了。這樣 agent 就會獲得 id 為1的進程
看完上述內容,你們掌握node中cluster集群的作用是什么的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。