【原創(chuàng)】學習NodeJs多進程(二)

前文介紹了NodeJs子進程創(chuàng)建和進程間通信,但讓開發(fā)者處理多進程的管理是比較麻煩的事情歌逢,通常開發(fā)者只希望關(guān)注業(yè)務代碼的實現(xiàn)签杈。本文介紹了多進程管理相關(guān)的cluster模塊、工具沽一、負載均衡等盖溺。

相關(guān)文章

目錄

  • cluster模塊
  • 負載均衡
  • 進程管理工具
  • cluster不適用的場景

cluster模塊

cluster模塊是對多進程創(chuàng)建、消息傳遞铣缠、共享端口的封裝烘嘱。以下為官方的使用示例昆禽,根據(jù)cpu數(shù)量創(chuàng)建工作進程,并監(jiān)聽同一個端口8000蝇庭。

const cluster = require('cluster')
const http = require('http')
const numCPUs = require('os').cpus().length

if (cluster.isMaster) {
  console.log(`Master ${process.pid} is running`)

  // Fork workers.
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork()
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`worker ${worker.process.pid} died`)
  })
} else {
  // Workers can share any TCP connection
  // In this case it is an HTTP server
  http.createServer((req, res) => {
    res.writeHead(200)
    res.end('hello world\n')
  }).listen(8000)

  console.log(`Worker ${process.pid} started`)
}

在前文介紹的多進程監(jiān)聽同一端口中醉鳖,主進程創(chuàng)建服務器,并將服務器句柄傳遞給子進程哮内,子進程再根據(jù)句柄還原服務器實例盗棵,請求到來時由操作系統(tǒng)調(diào)度機制決定交給哪個進程處理。以上由于保留了多個服務器實例直接監(jiān)聽同一端口北发,會造成資源浪費纹因,并且請求轉(zhuǎn)發(fā)不可控。

cluster模塊中默認以輪詢的方式處理請求琳拨,父進程創(chuàng)建內(nèi)部服務器并監(jiān)聽端口瞭恰,所有請求先經(jīng)過該服務器,再轉(zhuǎn)發(fā)給子進程處理从绘。由于父進程負責轉(zhuǎn)發(fā)寄疏,因此父進程可以指定負載均衡策略,另外父進程不直接處理業(yè)務邏輯僵井,可以保證父進程的穩(wěn)定性陕截。

cluster模塊提供豐富的api用來管理子進程,以下示例為子進程掛掉后自動創(chuàng)建新的進程:

const cluster = require('cluster')
const http = require('http')

cluster.schedulingPolicy = cluster.SCHED_RR

function listen (worker) {
  worker.on('message', (msg) => {
    console.log(`worker ${worker.process.pid}:`, msg)
  })
}

if (cluster.isMaster) {
  console.log(`master process ${process.pid} is running`)
  for (let i = 0; i < 4; i++) {
    cluster.fork()
  }

  for (const id in cluster.workers) {
    listen(cluster.workers[id])
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`worker process ${worker.process.pid} is exited`)
    listen(cluster.fork())
  })
} else {
  http.createServer((req, res) => {
    res.writeHead(200)
    res.end('hello world')

    process.send('handled request')
  }).listen(8000)

  console.log(`worker process ${process.pid} is running`)
}

訪問localhost:8000批什,再手動kill掉某一進程农曲,執(zhí)行結(jié)果如下:

master process 8616 is running
worker process 16332 is running
worker process 4624 is running
worker process 8084 is running
worker process 16352 is running
worker 16332: handled request
worker 15172: handled request
worker process 15172 is exited
worker process 2260 is running
worker 16332: handled request
worker 8084: handled request
worker 2260: handled request

可以看到,只要有子進程退出驻债,會自動創(chuàng)建子進程乳规。只要有工作進程存在,就能繼續(xù)處理請求合呐。

負載均衡

cluster模塊提供兩種負載均衡策略

  • cluster.SCHED_RR

    輪詢分發(fā)(除Windows外所有平臺的默認方法)暮的,由主進程負責監(jiān)聽端口,接收新連接后再將連接循環(huán)分發(fā)給工作進程淌实。在分發(fā)中使用了一些內(nèi)置技巧防止工作進程任務過載冻辩。

  • cluster.SCHED_NONE

    使用操作系統(tǒng)調(diào)度機制,主進程創(chuàng)建監(jiān)聽socket后發(fā)送給感興趣的工作進程拆祈,由工作進程負責直接接收連接恨闪。由于操作系統(tǒng)調(diào)度機制的難以捉摸,可能會使分發(fā)變得不穩(wěn)定放坏。在cluster模塊出現(xiàn)之前咙咽,多進程共同監(jiān)聽同一端口的調(diào)度方式都是用該機制。

使用cluster.schedulingPolicy可指定以上兩種策略淤年,也可以使用NODE_CLUSTER_SCHED_POLICY環(huán)境變量钧敞,對應以上的兩種策略的取值為rr蜡豹、none

cluster不支持自定義負載均衡策略犁享,可參考cluster的源碼余素,實現(xiàn)自己的負載均衡策略。根據(jù)cluster模塊源碼學習來理解多進程的負載均衡算法炊昆,文章地址:http://www.cnblogs.com/accordion/p/7207740.html

進程管理工具

在生產(chǎn)環(huán)境中桨吊,除了使用多進程充分利用cpu性能外,還需考慮進程異常退出的自動重啟凤巨,多個工作進程共享資源视乐,以及多進程之間的調(diào)度。cluster模塊只是對多進程創(chuàng)建敢茁、消息傳遞佑淀、共享端口的簡單封裝,下面介紹一些目前成熟的進程管理工具彰檬。

  • Pandora.js

    Pandora.js 是一個 Node.js 應用監(jiān)控管理器伸刃,它集成了多種類型的能力諸如:監(jiān)控、鏈路追蹤逢倍、調(diào)試捧颅、進程管理等等。它提供多進程模型较雕、多進程管理以及自定義進程擴展能力碉哑。開發(fā)者只需關(guān)注具體的業(yè)務邏輯實現(xiàn)即可。

  • pm2

    是一個進程管理工具亮蒋,維護一個進程列表扣典,可以用它來管理你的node進程,負責所有正在運行的進程慎玖,并查看node進程的狀態(tài)贮尖,也支持性能監(jiān)控,自動重啟趁怔,負載均衡等功能远舅,而且使用非常簡單。

  • Egg

    Egg雖然是企業(yè)級的NodeJs開發(fā)框架痕钢,但集成了egg-cluster模塊實現(xiàn)多進程的管理,自帶服務管理的cli序六,不需要其他的進程管理工具來管理進程了任连。另外提供Agent進程來處理不適合用多進程處理的場景,如定時任務例诀、websocket等随抠。

cluster不適用的場景

這里的cluster不止指node的cluster模塊裁着,也包括通過第三方庫實現(xiàn)的多進程管理工具。cluster雖然能充分利用服務器cpu資源拱她,提高服務的健壯性二驰,但并不是所有場景都適合用多進程來處理,比如:

  • 定時任務

    定時任務應該只被一個進程調(diào)用秉沼,如果以多進程的模式啟動桶雀,會造成定時任務的重復執(zhí)行。通常應該單獨創(chuàng)建一個進程來處理定時任務唬复,并且該進程應該保證穩(wěn)定性矗积,在發(fā)生異常錯誤時記錄錯誤而不自動退出。

  • socket.io

    socket.io是在websocket上封裝的敞咧,在客戶端未提供websocket功能的基礎(chǔ)上使用xhr polling棘捣、jsonp或forever iframe的方式進行兼容,同時在建立ws連接前往往通過幾次http輪詢確保websocket服務可用休建。在建立連接前的幾次http輪詢?nèi)绻晦D(zhuǎn)發(fā)到了不同的進程乍恐,會導致ws服務連接失敗。socket.io官方提供了nginx反向代理 + iphash的方式來保證同一個客戶端的多次請求定位到后端同一個服務進程测砂。關(guān)于socket.io的集群策略茵烈,可參考:https://segmentfault.com/a/1190000009622158

    • session和內(nèi)存緩存

    使用cluster模塊通常是無狀態(tài)應用,因為在進程中緩存的數(shù)據(jù)無法直接與其他進程共享邑彪,理論上可以在主進程上維護統(tǒng)一的緩存數(shù)據(jù)瞧毙,然后子進程從父進程中獲取,但邏輯上比較復雜寄症,并且增加了父進程的負擔宙彪。因此常常使用第三方工具來共享應用狀態(tài),如redis有巧。

總結(jié)

本文介紹了cluster模塊和常用的多進程管理工具释漆,希望對想要使用多進程來提升服務的性能和健壯性的小伙伴有一些幫助。

本文參考資源如下

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末篮迎,一起剝皮案震驚了整個濱河市男图,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌甜橱,老刑警劉巖逊笆,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異岂傲,居然都是意外死亡难裆,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乃戈,“玉大人褂痰,你說我怎么就攤上這事≈⒙牵” “怎么了缩歪?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長谍憔。 經(jīng)常有香客問我匪蝙,道長,這世上最難降的妖魔是什么韵卤? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任骗污,我火速辦了婚禮,結(jié)果婚禮上沈条,老公的妹妹穿的比我還像新娘需忿。我一直安慰自己,他們只是感情好蜡歹,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布屋厘。 她就那樣靜靜地躺著,像睡著了一般月而。 火紅的嫁衣襯著肌膚如雪汗洒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天父款,我揣著相機與錄音溢谤,去河邊找鬼。 笑死憨攒,一個胖子當著我的面吹牛世杀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播肝集,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瞻坝,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了杏瞻?” 一聲冷哼從身側(cè)響起所刀,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎捞挥,沒想到半個月后浮创,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡砌函,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年蒸矛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡雏掠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出劣像,到底是詐尸還是另有隱情乡话,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布耳奕,位于F島的核電站绑青,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏屋群。R本人自食惡果不足惜闸婴,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芍躏。 院中可真熱鬧邪乍,春花似錦、人聲如沸对竣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽否纬。三九已至吕晌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間临燃,已是汗流浹背睛驳。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留膜廊,地道東北人乏沸。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像溃论,于是被迫代替她去往敵國和親屎蜓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 在三年以前钥勋,如果要給自己貼個標簽的話炬转,我是怎么都不會給自己貼上“學習”的,這是因為算灸,從小學扼劈、初中、高中的學習經(jīng)歷都...
    巨曉松閱讀 813評論 1 3
  • 為什么感覺看了那么多的書菲驴,工作了那么多年荐吵,寫了那么多代碼,自己在一開始的進步明顯后,到現(xiàn)在基本停止進步先煎?我想是因為...
    聰安閱讀 523評論 0 0
  • 一面 一面的電話是8月13日打來的贼涩,約了14號下午7點,結(jié)果7點半才打來薯蝎。主要內(nèi)容: 自我介紹 看你項目用了Vue...
    C脖子閱讀 3,903評論 8 50
  • KVC: KVC也就是key-value-coding,即鍵值編碼遥倦,通常是用來給某一個對象的屬性進行賦值,例如有人...
    春暖花已開閱讀 497評論 0 3
  • 當今社會占锯,教育一直是家庭和社會中的大問題袒哥。學校被譽為教書育人之地,但目前傳授知識為主消略,育人為輔堡称。父母對子女的教育,...
    云在風中誰在聽閱讀 194評論 0 0