亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

前端進(jìn)階-讓你升級(jí)的網(wǎng)絡(luò)知識(shí)

leoperfect / 1201人閱讀

摘要:一般由客戶端發(fā)送,用來(lái)表示報(bào)文段中第一個(gè)數(shù)據(jù)字節(jié)在數(shù)據(jù)流中的序號(hào),主要用來(lái)解決網(wǎng)絡(luò)包亂序的問(wèn)題。為有效,為無(wú)效表示,當(dāng)數(shù)據(jù)包得到后,立馬給應(yīng)用程序使用到最頂端用來(lái)確保連接的安全。親,那進(jìn)程和線程區(qū)別是什么嘞這算是計(jì)算機(jī)的基本知識(shí)吧。

在正文之前,我想問(wèn)大家一個(gè)問(wèn)題:
問(wèn):親,你有基礎(chǔ)嗎?
答: 有啊,你說(shuō)前端嗎? 不就是HTML,JS,CSS 嗎? so easy~
問(wèn): oh-my-zsh... 好吧,那問(wèn)題來(lái)了,挖掘機(jī)技術(shù)哪家強(qiáng)... 開(kāi)玩笑。
現(xiàn)在才是問(wèn)題的正內(nèi)容。

你知道TCP的基本內(nèi)容嗎?(母雞啊~)

好吧,那你知道TCP的3次握手,4次揮手嗎?(知道一點(diǎn)點(diǎn))

恩,好,那什么是進(jìn)程呢?什么是線程呢?(母雞啊。。)

那并發(fā)和并行又是什么呢?(母雞啊)

OMG, 那nodeJS多進(jìn)程實(shí)現(xiàn)你會(huì)嗎?(不會(huì)呀~~~ md ...這都是些shenmegui)

其實(shí),說(shuō)多了都是淚,這些都是程序員的基本素質(zhì)呀。。。 面tencent的時(shí)候,被一個(gè)總監(jiān),罵的阿彌陀佛么么噠. 今天在這里和大家分享一下,我的血淚史。

TCP內(nèi)容

工欲善其事,必先利其器

一個(gè)程序員境界的提升,并不在于你寫(xiě)的一首好代碼,更在于你能說(shuō)出代碼背后的故事。ok~ 雞湯灌完了。我們開(kāi)始說(shuō)方法了。
首先這幅圖大家必須記得非常清楚才行。

對(duì)了還有,
OSI七層模型大家應(yīng)該爛熟于心的。

其中TCP處理transport層,主要是用來(lái)建立可靠的連接。 而建立連接的基礎(chǔ),是他豐富的報(bào)文內(nèi)容(md~超級(jí)多).我們先來(lái)解釋一下。 首先,我們TCP3次握手用的報(bào)文就是綠色的"TCP Flags"內(nèi)容。 通過(guò)發(fā)送ACK,SYN包實(shí)現(xiàn)。具體涉及的Tag詳見(jiàn):


Source Port / Destination Port:這個(gè)就是客戶端口(源端口)和服務(wù)器端口(目的端口). 端口就是用來(lái)區(qū)別主機(jī)中的不同進(jìn)程,通過(guò)結(jié)合源IP和目的IP結(jié)合,得出唯一的TCP連接。

Sequence Number(seqNumber): 一般由 客戶端發(fā)送,用來(lái)表示報(bào)文段中第一個(gè)數(shù)據(jù)字節(jié)在數(shù)據(jù)流中的序號(hào),主要用來(lái)解決網(wǎng)絡(luò)包亂序的問(wèn)題。

Acknowledgment Number(ACK): 即就是用來(lái)存放客戶端發(fā)來(lái)的seqNumber的下一個(gè)信號(hào)(seqNumber+1). 只有當(dāng) TCP flags中的ACK為1時(shí)才有效. 主要是用來(lái)解決不丟包的問(wèn)題。

TCP flags: TCP中有6個(gè)首部,用來(lái)控制TCP連接的狀態(tài).取值為0,1.這6個(gè)有:URG,ACK,PSH,RST,SYN,F(xiàn)IN.

URG 當(dāng)為1時(shí),用來(lái)保證TCP連接不被中斷, 并且將該次TCP內(nèi)容數(shù)據(jù)的緊急程度提升(就是告訴電腦,你丫趕快把這個(gè)給resolve了)

ACK 通常是服務(wù)器端返回的。 用來(lái)表示應(yīng)答是否有效。 1為有效,0為無(wú)效

PSH 表示,當(dāng)數(shù)據(jù)包得到后,立馬給應(yīng)用程序使用(PUSH到最頂端)

RST 用來(lái)確保TCP連接的安全。 該flag用來(lái)表示 一個(gè)連接復(fù)位的請(qǐng)求。 如果發(fā)生錯(cuò)誤連接,則reset一次,重新連。當(dāng)然也可以用來(lái)拒絕非法數(shù)據(jù)包。

SYN 同步的意思,通常是由客戶端發(fā)送,用來(lái)建立連接的。第一次握手時(shí): SYN:1 , ACK:0. 第二次握手時(shí): SYN:1 ACK:1

FIN 用來(lái)表示是否結(jié)束該次TCP連接。 通常當(dāng)你的數(shù)據(jù)發(fā)送完后,會(huì)自動(dòng)帶上FIN 然后斷開(kāi)連接

恩,基本的TCP內(nèi)容,大家應(yīng)該掌握了吧。OK, go on.

What"s TCP 3次握手

還是一樣, 先上張圖,讓大家先看一下。 上面大家已經(jīng)基本了解了TCP里面相應(yīng)的字段,現(xiàn)在看看圖里面的是不是覺(jué)得有些親切嘞?

其實(shí),大家看上面的圖,差不多都已經(jīng)能夠摸清楚,每次發(fā)送請(qǐng)求的內(nèi)容。其實(shí),TCP3次握手是為了建立 穩(wěn)定可靠的連接。所以也就不存在神馬 2次連接等的怪癖。
(圖中flag說(shuō)明:SYN包表示標(biāo)志位syn=1,ACK包表示標(biāo)志位ack=1,SYN+ACK包表示標(biāo)志位syn=1,ack=1)
現(xiàn)在,我們來(lái)正式進(jìn)入3次握手環(huán)節(jié)。

第一次握手. 客戶端向服務(wù)器發(fā)送一個(gè)SYN包,并且添加上seqNumber(假設(shè)為x),然后進(jìn)入SYN_SEND狀態(tài),并且等待服務(wù)器的確認(rèn)。

第二次握手: 服務(wù)器接受SYN包,并且進(jìn)行確認(rèn),如果該請(qǐng)求有效,則將TCP flags中的ACK 標(biāo)志位置1, 然后將AckNumber置為(seqNumber+1),并且再添加上自己的seqNumber(y), 完成后,返回給客戶端.服務(wù)器進(jìn)入SYN_RECV狀態(tài).(這里服務(wù)端是發(fā)送SYN+ACK包)

第三次握手 客戶端接受ACK+SYN報(bào)文后,獲取到服務(wù)器發(fā)送seqNumber(y), 并且 將新頭部的AckNumber變?yōu)?y+1).然后發(fā)送給服務(wù)器,完成TCP3次連接。此時(shí)服務(wù)器和客戶端都進(jìn)入ESTABLISHED狀態(tài).

回答一下這個(gè)比較尷尬的問(wèn)題,為什么只有3次握手,而不是4次,或者2次?
很簡(jiǎn)單呀,因?yàn)?次就夠了,干嘛用4次。23333. 舉個(gè)例子吧,假如是2次的話, 可能會(huì)出現(xiàn)這樣一個(gè)情況。

當(dāng)客戶端發(fā)送一次請(qǐng)求A后,但是A在網(wǎng)絡(luò)延遲了很久, 接著客戶端又發(fā)送了一次B,但是此時(shí)A已經(jīng)無(wú)效了。 接著服務(wù)器相應(yīng)了B,并返回TCP連接頭,建立連接(這里就2次哈)。 然后,A 歷經(jīng)千山萬(wàn)水終于到服務(wù)器了, 服務(wù)器一看有請(qǐng)求來(lái)了,則接受,由于一開(kāi)始A帶著的TCP格式都是正確的,那么服務(wù)器,理所應(yīng)當(dāng)?shù)囊卜祷爻晒B接的flag,但是,此時(shí)客戶端已經(jīng)判斷該次請(qǐng)求無(wú)效,廢棄了。 然后服務(wù)器,就這么一直掛著(浪費(fèi)資源),造成的一個(gè)問(wèn)題是,md, 這個(gè)鍋是誰(shuí)的? 所以,為了保險(xiǎn)起見(jiàn),再補(bǔ)充一次連接就可以了。所以3次是最合適的。在Chinese中,以3為起稱為,如果你用4,5,6,7,8...次的話,這不更浪費(fèi)嗎?

TCP4次揮手

TCP4次揮手,是比較簡(jiǎn)單的。大家對(duì)照上面那個(gè)圖,我們一步一步進(jìn)行一下講解。

第一次揮手: A機(jī)感覺(jué)此時(shí)如果keep-alive比較浪費(fèi)資源,則他提出了分手的請(qǐng)求。設(shè)置SeqNumberAckNumber之后,向B機(jī)發(fā)送FIN包, 表示我這已經(jīng)沒(méi)有數(shù)據(jù)給你了。然后A機(jī)進(jìn)入FIN_WAIT_1狀態(tài)

第二次揮手:B機(jī)收到了A機(jī)的FIN包,已經(jīng)知道了A機(jī)沒(méi)有數(shù)據(jù)再發(fā)送了。此時(shí)B機(jī)會(huì)給A機(jī)發(fā)送一個(gè)ACK包,并且將AckNumber 變?yōu)?A機(jī)傳輸來(lái)的SeqNumber+1. 當(dāng)A機(jī)接受到之后,則變?yōu)镕IN_WAIT_2狀態(tài)。表示已經(jīng)得到B機(jī)的許可,可以進(jìn)行關(guān)閉操作。不過(guò)此時(shí),B機(jī)還是可以向A機(jī)發(fā)送請(qǐng)求的。

第三次揮手 B機(jī)向A機(jī)發(fā)送FIN包,請(qǐng)求關(guān)閉,相當(dāng)于告訴A機(jī),我這里也沒(méi)有你要的數(shù)據(jù)了。然后B機(jī)進(jìn)入CLOSE_WAIT狀態(tài).(這里還需要帶上SeqNumber,大家看圖說(shuō)話就可以了)

第四次揮手 A機(jī)接收到B機(jī)的FIN包之后,然后同樣,發(fā)送一個(gè)ACK包給B機(jī)。 B機(jī)接受到之后,就斷開(kāi)了。 而A機(jī) 會(huì)等待2MSL之后,如果沒(méi)有回復(fù),確保服務(wù)器端確實(shí)是關(guān)閉了。然后A機(jī)也可以關(guān)閉連接。A,B都進(jìn)入了CLOSE狀態(tài).

明白了嗎?
大哥~ 等等,什么是2MSL呀~
哦,對(duì)哦。 這個(gè)還么說(shuō)...
2MSL=2*MSL. 而MSL其實(shí)就是Maximum Segment Lifetime,中文意思就是報(bào)文最大生存時(shí)間。RFC 793中規(guī)定MSL為2分鐘,實(shí)際應(yīng)用中常用的是30秒,1分鐘和2分鐘等。 同樣上面的TIME_WAT狀態(tài)其實(shí)也就是2MSL狀態(tài)。 如果超過(guò)改時(shí)間,則會(huì)將該報(bào)文廢棄,然后直接進(jìn)入CLOSED狀態(tài).

進(jìn)程?線程?

親,請(qǐng)問(wèn)php是一門什么語(yǔ)言? (提示,關(guān)于進(jìn)程)
官方回答: php是一門基于多線程的語(yǔ)言
親,請(qǐng)問(wèn)nodeJS是一門什么語(yǔ)言?(提示,關(guān)于線程)
官方回答: Node.js是單線程!異步!非阻塞!(不過(guò)早已可以實(shí)現(xiàn)多進(jìn)程交互了)
那php和nodeJS區(qū)別在哪呢?具體可以見(jiàn)圖:
PHP

NodeJS

ok~ 簡(jiǎn)單吧。
親,那進(jìn)程和線程區(qū)別是什么嘞?
go die /(ㄒoㄒ)/~~
這算是計(jì)算機(jī)的基本知識(shí)吧。 首先我們需要記住的是,進(jìn)程包括線程。這非常重要。

進(jìn)程就是系統(tǒng)分配資源的基本單位(比如CPU,內(nèi)存等)
線程就是程序執(zhí)行的最小單位

進(jìn)程有自己的空間,如果一個(gè)進(jìn)程崩潰不會(huì)引起其它進(jìn)程的崩潰。
線程,沒(méi)有自己獨(dú)立的空間,多個(gè)線程共享的是進(jìn)程的地址空間,當(dāng)然處理一些基本的如程序計(jì)數(shù)器,一組寄存器和棧等。
如果一個(gè)線程崩潰,它所在的進(jìn)程就崩潰了。 雖然說(shuō),多進(jìn)程很穩(wěn)定,但是進(jìn)程切換時(shí),耗費(fèi)的資源也是很大的。 所以對(duì)于大并發(fā)的nodeJS來(lái)說(shuō),使用多線程的效果要遠(yuǎn)遠(yuǎn)比多進(jìn)程快,穩(wěn)定。

線程的優(yōu)勢(shì)

1.系統(tǒng)在啟動(dòng)一個(gè)進(jìn)程的時(shí)候,會(huì)首先在資源中獨(dú)立一塊出來(lái),在后臺(tái)建立一些列表進(jìn)行維護(hù)。 而,線程是比進(jìn)程低一個(gè)level的,所以創(chuàng)建線程所耗費(fèi)的資源要遠(yuǎn)遠(yuǎn)比,創(chuàng)建進(jìn)程的資源少。

由于進(jìn)程本身就比較復(fù)雜,所以如果進(jìn)行進(jìn)程切換的話,造成的性能損耗也是不言而喻的(因?yàn)槎鄠€(gè)進(jìn)程獨(dú)立,在切換的時(shí)候還需要保證各自的獨(dú)立性)。 而線程切換就不同了,因?yàn)樵谔幵谕贿M(jìn)程下面,對(duì)于其他的進(jìn)程都是透明化的(內(nèi)存共享),所以在進(jìn)行進(jìn)程切換時(shí),所耗費(fèi)的資源遠(yuǎn)遠(yuǎn)比進(jìn)程切換的小。

在Linux和window下,CPU的分配是根據(jù)線程數(shù)來(lái)的,如果

總線程數(shù)<= CPU數(shù)量:并行運(yùn)行
總線程數(shù)> CPU數(shù)量:并發(fā)運(yùn)行

并行指的是,當(dāng)你的CPU核數(shù)比線程數(shù)多的話,則會(huì)將每個(gè)線程都分在一個(gè)CPU核里進(jìn)行處理。

并發(fā)指的是,當(dāng)你的CPU核數(shù)比線程數(shù)少的話,則會(huì)利用“時(shí)間片輪轉(zhuǎn)進(jìn)程調(diào)度算法”,對(duì)每個(gè)線程進(jìn)行同等的運(yùn)行。

4.細(xì)化進(jìn)程的處理,通常一個(gè)進(jìn)程可以拆分為多個(gè)線程進(jìn)行處理,就和模塊化處理是類似的,使用模塊化書(shū)寫(xiě)的效果要遠(yuǎn)遠(yuǎn)比使用單main入口方式書(shū)寫(xiě) 清晰,穩(wěn)定。

并發(fā),并行原理

親, 并發(fā)和并行有什么共同點(diǎn)嗎?
恩~ 有的, 他們都有個(gè)‘并’子,字面上看起來(lái)都是同時(shí)執(zhí)行的意思。
沒(méi)錯(cuò),當(dāng)然只是字面上而已。
實(shí)際上,并發(fā)和并行是完全不同的概念。 這里主要和CPU核數(shù)有關(guān)。這里為了理解,拿線程來(lái)作為參考吧。
當(dāng)你的

總線程數(shù)<= CPU數(shù)量:并行運(yùn)行
總線程數(shù)> CPU數(shù)量:并發(fā)運(yùn)行

很明顯,并行其實(shí)是真正意義上的同時(shí)執(zhí)行。 當(dāng)線程數(shù)< CPU核數(shù)時(shí),每個(gè)線程會(huì)獨(dú)立分配到一個(gè)CPU里進(jìn)行處理。
大家看過(guò)火影忍者嗎?
沒(méi)錯(cuò),就是鳴人 出關(guān) 口遁九尾之后。 他使用影分身,跑去各地支援同伴,對(duì)抗斑。 這里類比來(lái)說(shuō),就可以理解為, 每個(gè)CPU 都是鳴人的一個(gè)影分身,他們執(zhí)行這各自不同的工作,但是,在同一時(shí)間上,他們都在運(yùn)行。 這就是并行。
那并發(fā)嘞?
其實(shí),并發(fā)有點(diǎn)難以理解,他做的工作其實(shí),就是利用一系列算法實(shí)現(xiàn),并行做的事。一個(gè)比較容易理解的就是“時(shí)間片輪轉(zhuǎn)進(jìn)程調(diào)度算法”。
即: 在系統(tǒng)控制下,每個(gè)線程輪流使用CPU,而且,每個(gè)線程使用時(shí)間必須很短(比如10ms), 所以這樣切換下來(lái)。我們(愚蠢的人類,哈哈哈), 天真的以為任務(wù),真的是在"并行"執(zhí)行.

nodeJS的進(jìn)程實(shí)現(xiàn)

一開(kāi)始nodeJS最令人詬病的就是他的單線程特性。既是絕招也是死穴,不過(guò)nodeJS發(fā)展很快,在v0.8版本就已經(jīng)添加了cluster作為內(nèi)置模塊,實(shí)現(xiàn)多核的利用。
關(guān)于nodeJS的進(jìn)程模塊,最主要的當(dāng)然還是cluster. 通過(guò)調(diào)用child_process.fork()函數(shù)來(lái)開(kāi)啟進(jìn)程。 先看一個(gè)具體的demo(from 官網(wǎng))

var cluster = require("cluster");
var http = require("http");
var numCPUs = require("os").cpus().length;

if (cluster.isMaster) {
    console.log("master start...");

    // Fork workers.
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }
    //用來(lái)監(jiān)聽(tīng)子worker創(chuàng)建監(jiān)聽(tīng)服務(wù)
    cluster.on("listening",function(worker,address){
        console.log("listening: worker " + worker.process.pid +", Address: "+address.address+":"+address.port);
    });

    cluster.on("exit", function(worker, code, signal) {
        console.log("worker " + worker.process.pid + " died");
    });
} else {
    http.createServer(function(req, res) {
        res.writeHead(200);
        res.end("hello world
");
    }).listen(0);
}

存放為app.js 然后運(yùn)行node app.js就可以實(shí)現(xiàn)一個(gè)簡(jiǎn)單的多進(jìn)程效果。
結(jié)果可能為下:

master start...
listening: worker 1559, Address: null:57803
listening: worker 1556, Address: null:57803
listening: worker 1558, Address: null:57803
listening: worker 1557, Address: null:57803

可以從上面的demo中看出,通過(guò)cluster.isMaster來(lái)區(qū)分master和worker. 而master和worker之間使用listen(0)進(jìn)行通信.

server.listen(0):在master和worker通信過(guò)程,集群中的worker會(huì)打開(kāi)一個(gè)隨機(jī)端口共用,通過(guò)socket通信像上例中的57803

當(dāng)然你也可以手動(dòng)打開(kāi)一個(gè)端口共享監(jiān)聽(tīng)。像這樣.

 http.createServer(function(req, res) {
        res.writeHead(200);
        res.end("hello world
");
    }).listen(3000);
cluster對(duì)應(yīng)API

cluster對(duì)象的屬性和函數(shù)

cluster.setttings:配置集群參數(shù)對(duì)象

cluster.isMaster:判斷是不是master節(jié)點(diǎn)*

cluster.isWorker:判斷是不是worker節(jié)點(diǎn)*

Event: "fork": 監(jiān)聽(tīng)創(chuàng)建worker進(jìn)程事件

Event: "online": 監(jiān)聽(tīng)worker創(chuàng)建成功事件

Event: "listening": 監(jiān)聽(tīng)worker開(kāi)啟的http.listen

Event: "disconnect": 監(jiān)聽(tīng)worker斷線事件

Event: "exit": 監(jiān)聽(tīng)worker退出事件

Event: "setup": 監(jiān)聽(tīng)setupMaster事件

cluster.setupMaster([settings]): 設(shè)置集群參數(shù)

cluster.fork([env]): 創(chuàng)建worker進(jìn)程

cluster.disconnect([callback]): 關(guān)閉worket進(jìn)程*

cluster.worker: 獲得當(dāng)前的worker對(duì)象*

cluster.workers: 獲得集群中所有存活的worker對(duì)象*

通過(guò)cluster.worker獲得的worker對(duì)象和相應(yīng)的參數(shù)

worker.id: 進(jìn)程ID號(hào)

worker.process: ChildProcess對(duì)象*

worker.suicide: 在disconnect()后,判斷worker是否自殺*

worker.send(message, [sendHandle]):* master給worker發(fā)送消息。注:worker給發(fā)master發(fā)送消息要用process.send(message)

worker.kill([signal="SIGTERM"]): 殺死指定的worker,別名destory()*

worker.disconnect(): 斷開(kāi)worker連接,讓worker自殺

Event: "message": 監(jiān)聽(tīng)master和worker的message事件

Event: "online": 監(jiān)聽(tīng)指定的worker創(chuàng)建成功事件

Event: "listening": 監(jiān)聽(tīng)master向worker狀態(tài)事件

Event: "disconnect": 監(jiān)聽(tīng)worker斷線事件

Event: "exit": 監(jiān)聽(tīng)worker退出事件

這些就是cluster的全部?jī)?nèi)容。不過(guò)這僅僅只是內(nèi)容而已,如果使用cluster,這便是我們程序員要做的事了。

進(jìn)程通信

由于nodeJS 只能實(shí)現(xiàn)單進(jìn)程的效果,所以他的進(jìn)程數(shù)只能為一個(gè),但是通過(guò)引用cluster模塊,可以開(kāi)啟多個(gè)子進(jìn)程實(shí)現(xiàn)CPU的利用。
簡(jiǎn)單進(jìn)程交互
運(yùn)行后的結(jié)果為:

[master] start master...
[master] fork: worker1
[master] fork: worker2
[master] fork: worker3
[master] fork: worker4
[master] online: worker1
[master] online: worker4
[master] online: worker2
[master] online: worker3
[worker] start worker ...1
[worker] start worker ...4
[worker] start worker ...2
[master] listening: worker4,pid:990, Address:null:3000
[master] listening: worker1,pid:987, Address:null:3000
[master] listening: worker2,pid:988, Address:null:3000
[worker] start worker ...3
[master] listening: worker3,pid:989, Address:null:3000

參照注釋代碼和上述的結(jié)果,我們可以很容易的得到一個(gè)觸發(fā)邏輯。
運(yùn)行過(guò)程是:

首先f(wàn)ork子進(jìn)程

觸發(fā)fork事件

創(chuàng)建成功,觸發(fā)online事件

然后重新執(zhí)行一遍app.js,通過(guò)isWorker判斷子進(jìn)程

創(chuàng)建子進(jìn)程服務(wù)->觸發(fā)master上的listening

st=>start: 首先f(wàn)ork子進(jìn)程
op1=>operation: 觸發(fā)fork事件
op2=>operation: 創(chuàng)建成功,觸發(fā)online事件
op3=>operation: 然后重新執(zhí)行一遍app.js,通過(guò)isWorker判斷子進(jìn)程
op4=>operation: 創(chuàng)建子進(jìn)程服務(wù)->觸發(fā)master上的listening
e=>end

st->op1->op2->op3->op4->e

上面只是創(chuàng)建滿負(fù)載子進(jìn)程的流程。 但怎樣實(shí)現(xiàn)進(jìn)程間的交互呢? 很簡(jiǎn)單,master和worker監(jiān)聽(tīng)message事件,通過(guò)傳遞參數(shù),進(jìn)行交互。

cluster.worker.send(message[,handleFn]) master向worker發(fā)送信息

process.send(message[,handleFn]); worker向master發(fā)送信息

這個(gè)是多進(jìn)程之間的通信
communication
我們來(lái)分解一下代碼塊:

//開(kāi)啟master監(jiān)聽(tīng)worker的通信
cluster.workers[id].on("message", function(msg){
          //...
        });
        
//開(kāi)啟worker監(jiān)聽(tīng)master的通信
process.on("message", function(msg) {
       //...
    });

運(yùn)行上面的demo. 這里就不細(xì)說(shuō),整個(gè)流程,只看一下信息通信這一塊了。

創(chuàng)建子進(jìn)程,觸發(fā)listening事件

使用process.on監(jiān)聽(tīng)message

接受master發(fā)送過(guò)來(lái)的消息

再向master返回消息

st=>start: 創(chuàng)建子進(jìn)程,觸發(fā)listening事件
op1=>operation: 使用process.on監(jiān)聽(tīng)message
op2=>operation: 接受master發(fā)送過(guò)來(lái)的消息
op3=>operation: 再向master返回消息
op4=>operation: others
e=>others

st->op1->op2->op3->op4
nodeJS負(fù)載均衡

現(xiàn)在,nodeJS負(fù)載均衡應(yīng)該是最容易實(shí)現(xiàn)的,其內(nèi)部已經(jīng)幫我們封裝好了,我們直接調(diào)用就over了。
其中,實(shí)現(xiàn)負(fù)載均衡的模塊就是cluster。以前cluster確實(shí)很累贅。負(fù)載均衡的算法實(shí)現(xiàn)的不是很好,導(dǎo)致的下場(chǎng)就是npm2的興起。不過(guò)現(xiàn)在已經(jīng)實(shí)現(xiàn)了負(fù)載均衡,官方說(shuō)法就是用round-robin,來(lái)進(jìn)行請(qǐng)求分配。 round-robin其實(shí)就是一個(gè)隊(duì)列的循環(huán),灰常容易理解。先看一下,cluster封裝好實(shí)現(xiàn)的負(fù)載均衡.

var cluster = require("cluster");
var http = require("http");
var numCPUs = require("os").cpus().length;

if (cluster.isMaster) {
    console.log("[master] " + "start master...");

    for (var i = 0; i < numCPUs; i++) {
         cluster.fork();
    }

    cluster.on("listening", function (worker, address) {
        console.log("[master] " + "listening: worker" + worker.id + ",pid:" + worker.process.pid + ", Address:" + address.address + ":" + address.port);
    });

} else if (cluster.isWorker) {
     console.log("[worker] " + "start worker ..." + cluster.worker.id);
    var num = 0;
    http.createServer(function (req, res) {
        num++;
        console.log("worker"+cluster.worker.id+":"+num);
        res.end("worker"+cluster.worker.id+",PID:"+process.pid);
    }).listen(3000);
}

(哥哥,你騙人,這哪里實(shí)現(xiàn)了負(fù)載均衡,這不就是上面的算法么?)
是呀,,, 我又沒(méi)說(shuō)負(fù)載均衡不是這個(gè)。
負(fù)載均衡就是幫你解決請(qǐng)求的分配問(wèn)題。ok~ 為了證明,我沒(méi)有騙你,我們來(lái)進(jìn)行測(cè)試一下。
使用brew安裝siege測(cè)試,當(dāng)然你也可以使用其他測(cè)試工具,不過(guò)在MAC 上面最好使用siege和webbench或者ab,我這里使用siege

brew install siege

使用的測(cè)試語(yǔ)法就是

siege -c 并發(fā)數(shù) -t 運(yùn)行測(cè)試時(shí)間 URL

測(cè)試的時(shí)間后面需要帶上單位,比如s,m,h,d等。默認(rèn)單位是m(分鐘). 舉個(gè)例子吧.

siege -c 100 -t 10s http://girls.hustonline.net

對(duì)女生節(jié)網(wǎng)頁(yè)進(jìn)行 100次并發(fā)測(cè)試,持續(xù)時(shí)間是10s.
當(dāng)然siege里還有其他的參數(shù).

-c NUM 設(shè)置并發(fā)的數(shù)量.eg: -c 100; //設(shè)置100次并發(fā)

-r NUM 設(shè)置發(fā)送幾輪的請(qǐng)求,即,總的請(qǐng)求數(shù)為: -cNum*-rNum但是, -r不能和-t一起使用(為什么呢?你猜).eg: -r 20

-t NUM 測(cè)試持續(xù)時(shí)間,指你運(yùn)行一次測(cè)試需要的時(shí)間,在timeout后,結(jié)束測(cè)試.

-f file. 用來(lái)測(cè)試file里面的url路徑.file的尾綴需要為.url. eg: -f girls.url.

-b . 就是詢問(wèn)開(kāi)不開(kāi)啟基準(zhǔn)測(cè)試(benchmark)。 這個(gè)參數(shù)不太重要,有興趣的同學(xué),可以下去學(xué)習(xí)一下。

siege常用的就是這幾個(gè). 通常我們是搭配 -c + -r 或者-c + -t.
OK,現(xiàn)在我們開(kāi)始我們的測(cè)試 procedure.
首先開(kāi)啟多進(jìn)程N(yùn)odeJS. node app.js
使用siege -c 100 -t 10s 127.0.0.1:3000. (Ps: 當(dāng)然也可以使用http://localhost:3000進(jìn)行代替)
得到的結(jié)果為

Transactions:                 600 hits
Availability:              100.00 %
Elapsed time:                6.08 secs
Data transferred:            0.01 MB
Response time:                0.01 secs
Transaction rate:           98.68 trans/sec
Throughput:                0.00 MB/sec
Concurrency:                0.88
Successful transactions:         600
Failed transactions:               0
Longest transaction:            0.04
Shortest transaction:            0.00

在10s內(nèi),發(fā)起了600次請(qǐng)求,最大的峰值是98.68 trans/sec。 通過(guò)統(tǒng)計(jì)分析,得到每個(gè)worker的分發(fā)量.

worker1:162
worker2:161
worker3:167
worker4:170

可以看出,基本上每個(gè)負(fù)載上分配的請(qǐng)求的數(shù)目都差不多。這就已經(jīng)達(dá)到了負(fù)載均衡的效果。
下一篇會(huì)對(duì)nodeJS已經(jīng)相關(guān)的測(cè)試工具做一些介紹哦。
盡請(qǐng)期待。
ending~

大家如果感興趣,給我一杯咖啡喝喝吧~

轉(zhuǎn)載請(qǐng)注明出處和作者
原文連接:https://segmentfault.com/a/1190000004569460

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/8733.html

相關(guān)文章

  • 個(gè)人分享--web前端學(xué)習(xí)資源分享

    摘要:前言月份開(kāi)始出沒(méi)社區(qū),現(xiàn)在差不多月了,按照工作的說(shuō)法,就是差不多過(guò)了三個(gè)月的試用期,準(zhǔn)備轉(zhuǎn)正了一般來(lái)說(shuō),差不多到了轉(zhuǎn)正的時(shí)候,會(huì)進(jìn)行總結(jié)或者分享會(huì)議那么今天我就把看過(guò)的一些學(xué)習(xí)資源主要是博客,博文推薦分享給大家。 1.前言 6月份開(kāi)始出沒(méi)社區(qū),現(xiàn)在差不多9月了,按照工作的說(shuō)法,就是差不多過(guò)了三個(gè)月的試用期,準(zhǔn)備轉(zhuǎn)正了!一般來(lái)說(shuō),差不多到了轉(zhuǎn)正的時(shí)候,會(huì)進(jìn)行總結(jié)或者分享會(huì)議!那么今天我就...

    sherlock221 評(píng)論0 收藏0
  • 前端資源系列(4)-前端學(xué)習(xí)資源分享&前端面試資源匯總

    摘要:特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 本以為自己收藏的站點(diǎn)多,可以很快搞定,沒(méi)想到一入?yún)R總深似海。還有很多不足&遺漏的地方,歡迎補(bǔ)充。有錯(cuò)誤的地方,還請(qǐng)斧正... 托管: welcome to git,歡迎交流,感謝star 有好友反應(yīng)和斧正,會(huì)及時(shí)更新,平時(shí)業(yè)務(wù)工作時(shí)也會(huì)不定期更...

    princekin 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<