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