摘要:如需了解更多物聯(lián)網(wǎng)網(wǎng)絡(luò)編程知識(shí)請(qǐng)點(diǎn)擊物聯(lián)網(wǎng)云端開(kāi)發(fā)武器庫(kù)物聯(lián)網(wǎng)高并發(fā)編程之網(wǎng)絡(luò)編程中的線(xiàn)程模型值得說(shuō)明的是,具體選擇線(xiàn)程還是進(jìn)程,更多是與平臺(tái)及編程語(yǔ)言相關(guān)。
如需了解更多物聯(lián)網(wǎng)網(wǎng)絡(luò)編程知識(shí)請(qǐng)點(diǎn)擊:物聯(lián)網(wǎng)云端開(kāi)發(fā)武器庫(kù)
物聯(lián)網(wǎng)高并發(fā)編程之網(wǎng)絡(luò)編程中的線(xiàn)程模型值得說(shuō)明的是,具體選擇線(xiàn)程還是進(jìn)程,更多是與平臺(tái)及編程語(yǔ)言相關(guān)。
例如 C 語(yǔ)言使用線(xiàn)程和進(jìn)程都可以(例如 Nginx 使用進(jìn)程,Memcached 使用線(xiàn)程),Java 語(yǔ)言一般使用線(xiàn)程(例如 Netty),為了描述方便,下面都使用線(xiàn)程來(lái)進(jìn)行描述。
特點(diǎn):
1)采用阻塞式 I/O 模型獲取輸入數(shù)據(jù);
2)每個(gè)連接都需要獨(dú)立的線(xiàn)程完成數(shù)據(jù)輸入,業(yè)務(wù)處理,數(shù)據(jù)返回的完整操作。
存在問(wèn)題:
1)當(dāng)并發(fā)數(shù)較大時(shí),需要?jiǎng)?chuàng)建大量線(xiàn)程來(lái)處理連接,系統(tǒng)資源占用較大;
2)連接建立后,如果當(dāng)前線(xiàn)程暫時(shí)沒(méi)有數(shù)據(jù)可讀,則線(xiàn)程就阻塞在 Read 操作上,造成線(xiàn)程資源浪費(fèi)。
線(xiàn)程模型2:Reactor 模式 基本介紹針對(duì)傳統(tǒng)阻塞 I/O 服務(wù)模型的 2 個(gè)缺點(diǎn),比較常見(jiàn)的有如下解決方案:?
1)基于 I/O 復(fù)用模型:多個(gè)連接共用一個(gè)阻塞對(duì)象,應(yīng)用程序只需要在一個(gè)阻塞對(duì)象上等待,無(wú)需阻塞等待所有連接。當(dāng)某條連接有新的數(shù)據(jù)可以處理時(shí),操作系統(tǒng)通知應(yīng)用程序,線(xiàn)程從阻塞狀態(tài)返回,開(kāi)始進(jìn)行業(yè)務(wù)處理;
2)基于線(xiàn)程池復(fù)用線(xiàn)程資源:不必再為每個(gè)連接創(chuàng)建線(xiàn)程,將連接完成后的業(yè)務(wù)處理任務(wù)分配給線(xiàn)程進(jìn)行處理,一個(gè)線(xiàn)程可以處理多個(gè)連接的業(yè)務(wù)。
Reactor 模式,是指通過(guò)一個(gè)或多個(gè)輸入同時(shí)傳遞給服務(wù)處理器的服務(wù)請(qǐng)求的事件驅(qū)動(dòng)處理模式。?
服務(wù)端程序處理傳入多路請(qǐng)求,并將它們同步分派給請(qǐng)求對(duì)應(yīng)的處理線(xiàn)程,Reactor 模式也叫 Dispatcher 模式。
即 I/O 多了復(fù)用統(tǒng)一監(jiān)聽(tīng)事件,收到事件后分發(fā)(Dispatch 給某進(jìn)程),是編寫(xiě)高性能網(wǎng)絡(luò)服務(wù)器的必備技術(shù)之一。
Reactor 模式中有 2 個(gè)關(guān)鍵組成:
1)Reactor:Reactor 在一個(gè)多帶帶的線(xiàn)程中運(yùn)行,負(fù)責(zé)監(jiān)聽(tīng)和分發(fā)事件,分發(fā)給適當(dāng)?shù)奶幚沓绦騺?lái)對(duì) IO 事件做出反應(yīng)。 它就像公司的電話(huà)接線(xiàn)員,它接聽(tīng)來(lái)自客戶(hù)的電話(huà)并將線(xiàn)路轉(zhuǎn)移到適當(dāng)?shù)穆?lián)系人;
2)Handlers:處理程序執(zhí)行 I/O 事件要完成的實(shí)際事件,類(lèi)似于客戶(hù)想要與之交談的公司中的實(shí)際官員。Reactor 通過(guò)調(diào)度適當(dāng)?shù)奶幚沓绦騺?lái)響應(yīng) I/O 事件,處理程序執(zhí)行非阻塞操作。
根據(jù) Reactor 的數(shù)量和處理資源池線(xiàn)程的數(shù)量不同,有 3 種典型的實(shí)現(xiàn):
1)單 Reactor 單線(xiàn)程;
2)單 Reactor 多線(xiàn)程;
3)主從 Reactor 多線(xiàn)程。
其中,Select 是前面 I/O 復(fù)用模型介紹的標(biāo)準(zhǔn)網(wǎng)絡(luò)編程 API,可以實(shí)現(xiàn)應(yīng)用程序通過(guò)一個(gè)阻塞對(duì)象監(jiān)聽(tīng)多路連接請(qǐng)求,其他方案示意圖類(lèi)似。
方案說(shuō)明:
1)Reactor 對(duì)象通過(guò) Select 監(jiān)控客戶(hù)端請(qǐng)求事件,收到事件后通過(guò) Dispatch 進(jìn)行分發(fā);
2)如果是建立連接請(qǐng)求事件,則由 Acceptor 通過(guò) Accept 處理連接請(qǐng)求,然后創(chuàng)建一個(gè) Handler 對(duì)象處理連接完成后的后續(xù)業(yè)務(wù)處理;
3)如果不是建立連接事件,則 Reactor 會(huì)分發(fā)調(diào)用連接對(duì)應(yīng)的 Handler 來(lái)響應(yīng);
4)Handler 會(huì)完成 Read→業(yè)務(wù)處理→Send 的完整業(yè)務(wù)流程。
優(yōu)點(diǎn):模型簡(jiǎn)單,沒(méi)有多線(xiàn)程、進(jìn)程通信、競(jìng)爭(zhēng)的問(wèn)題,全部都在一個(gè)線(xiàn)程中完成。
缺點(diǎn):性能問(wèn)題,只有一個(gè)線(xiàn)程,無(wú)法完全發(fā)揮多核 CPU 的性能。Handler 在處理某個(gè)連接上的業(yè)務(wù)時(shí),整個(gè)進(jìn)程無(wú)法處理其他連接事件,很容易導(dǎo)致性能瓶頸。
可靠性問(wèn)題,線(xiàn)程意外跑飛,或者進(jìn)入死循環(huán),會(huì)導(dǎo)致整個(gè)系統(tǒng)通信模塊不可用,不能接收和處理外部消息,造成節(jié)點(diǎn)故障。
使用場(chǎng)景:客戶(hù)端的數(shù)量有限,業(yè)務(wù)處理非??焖伲热?Redis,業(yè)務(wù)處理的時(shí)間復(fù)雜度 O(1)。
單 Reactor 多線(xiàn)程方案說(shuō)明:
1)Reactor 對(duì)象通過(guò) Select 監(jiān)控客戶(hù)端請(qǐng)求事件,收到事件后通過(guò) Dispatch 進(jìn)行分發(fā);
2)如果是建立連接請(qǐng)求事件,則由 Acceptor 通過(guò) Accept 處理連接請(qǐng)求,然后創(chuàng)建一個(gè) Handler 對(duì)象處理連接完成后續(xù)的各種事件;
3)如果不是建立連接事件,則 Reactor 會(huì)分發(fā)調(diào)用連接對(duì)應(yīng)的 Handler 來(lái)響應(yīng);
4)Handler 只負(fù)責(zé)響應(yīng)事件,不做具體業(yè)務(wù)處理,通過(guò) Read 讀取數(shù)據(jù)后,會(huì)分發(fā)給后面的 Worker 線(xiàn)程池進(jìn)行業(yè)務(wù)處理;
5)Worker 線(xiàn)程池會(huì)分配獨(dú)立的線(xiàn)程完成真正的業(yè)務(wù)處理,將響應(yīng)結(jié)果發(fā)給 Handler 進(jìn)行處理;
6)Handler 收到響應(yīng)結(jié)果后通過(guò) Send 將響應(yīng)結(jié)果返回給 Client。
優(yōu)點(diǎn):可以充分利用多核 CPU 的處理能力。
缺點(diǎn):多線(xiàn)程數(shù)據(jù)共享和訪(fǎng)問(wèn)比較復(fù)雜;Reactor 承擔(dān)所有事件的監(jiān)聽(tīng)和響應(yīng),在單線(xiàn)程中運(yùn)行,高并發(fā)場(chǎng)景下容易成為性能瓶頸。
針對(duì)單 Reactor 多線(xiàn)程模型中,Reactor 在單線(xiàn)程中運(yùn)行,高并發(fā)場(chǎng)景下容易成為性能瓶頸,可以讓 Reactor 在多線(xiàn)程中運(yùn)行。
方案說(shuō)明:
1)Reactor 主線(xiàn)程 MainReactor 對(duì)象通過(guò) Select 監(jiān)控建立連接事件,收到事件后通過(guò) Acceptor 接收,處理建立連接事件;
2)Acceptor 處理建立連接事件后,MainReactor 將連接分配 Reactor 子線(xiàn)程給 SubReactor 進(jìn)行處理;
3)SubReactor 將連接加入連接隊(duì)列進(jìn)行監(jiān)聽(tīng),并創(chuàng)建一個(gè) Handler 用于處理各種連接事件;
4)當(dāng)有新的事件發(fā)生時(shí),SubReactor 會(huì)調(diào)用連接對(duì)應(yīng)的 Handler 進(jìn)行響應(yīng);
5)Handler 通過(guò) Read 讀取數(shù)據(jù)后,會(huì)分發(fā)給后面的 Worker 線(xiàn)程池進(jìn)行業(yè)務(wù)處理;
6)Worker 線(xiàn)程池會(huì)分配獨(dú)立的線(xiàn)程完成真正的業(yè)務(wù)處理,如何將響應(yīng)結(jié)果發(fā)給 Handler 進(jìn)行處理;
7)Handler 收到響應(yīng)結(jié)果后通過(guò) Send 將響應(yīng)結(jié)果返回給 Client。
優(yōu)點(diǎn):父線(xiàn)程與子線(xiàn)程的數(shù)據(jù)交互簡(jiǎn)單職責(zé)明確,父線(xiàn)程只需要接收新連接,子線(xiàn)程完成后續(xù)的業(yè)務(wù)處理。
父線(xiàn)程與子線(xiàn)程的數(shù)據(jù)交互簡(jiǎn)單,Reactor 主線(xiàn)程只需要把新連接傳給子線(xiàn)程,子線(xiàn)程無(wú)需返回?cái)?shù)據(jù)。
這種模型在許多項(xiàng)目中廣泛使用,包括 Nginx 主從 Reactor 多進(jìn)程模型,Memcached 主從多線(xiàn)程,Netty 主從多線(xiàn)程模型的支持。
小結(jié)3 種模式可以用個(gè)比喻來(lái)理解:(餐廳常常雇傭接待員負(fù)責(zé)迎接顧客,當(dāng)顧客入坐后,侍應(yīng)生專(zhuān)門(mén)為這張桌子服務(wù))
1)單 Reactor 單線(xiàn)程,接待員和侍應(yīng)生是同一個(gè)人,全程為顧客服務(wù);
2)單 Reactor 多線(xiàn)程,1 個(gè)接待員,多個(gè)侍應(yīng)生,接待員只負(fù)責(zé)接待;
3)主從 Reactor 多線(xiàn)程,多個(gè)接待員,多個(gè)侍應(yīng)生。
Reactor 模式具有如下的優(yōu)點(diǎn):
1)響應(yīng)快,不必為單個(gè)同步時(shí)間所阻塞,雖然 Reactor 本身依然是同步的;
2)編程相對(duì)簡(jiǎn)單,可以最大程度的避免復(fù)雜的多線(xiàn)程及同步問(wèn)題,并且避免了多線(xiàn)程/進(jìn)程的切換開(kāi)銷(xiāo);
3)可擴(kuò)展性,可以方便的通過(guò)增加 Reactor 實(shí)例個(gè)數(shù)來(lái)充分利用 CPU 資源;
4)可復(fù)用性,Reactor 模型本身與具體事件處理邏輯無(wú)關(guān),具有很高的復(fù)用性。
線(xiàn)程模型2:Proactor 模型在 Reactor 模式中,Reactor 等待某個(gè)事件或者可應(yīng)用或者操作的狀態(tài)發(fā)生(比如文件描述符可讀寫(xiě),或者是 Socket 可讀寫(xiě))。
然后把這個(gè)事件傳給事先注冊(cè)的 Handler(事件處理函數(shù)或者回調(diào)函數(shù)),由后者來(lái)做實(shí)際的讀寫(xiě)操作。
其中的讀寫(xiě)操作都需要應(yīng)用程序同步操作,所以 Reactor 是非阻塞同步網(wǎng)絡(luò)模型。
如果把 I/O 操作改為異步,即交給操作系統(tǒng)來(lái)完成就能進(jìn)一步提升性能,這就是異步網(wǎng)絡(luò)模型 Proactor。
Proactor 是和異步 I/O 相關(guān)的,詳細(xì)方案如下:
1)Proactor Initiator 創(chuàng)建 Proactor 和 Handler 對(duì)象,并將 Proactor 和 Handler 都通過(guò) AsyOptProcessor(Asynchronous Operation Processor)注冊(cè)到內(nèi)核;
2)AsyOptProcessor 處理注冊(cè)請(qǐng)求,并處理 I/O 操作;
3)AsyOptProcessor 完成 I/O 操作后通知 Proactor;
4)Proactor 根據(jù)不同的事件類(lèi)型回調(diào)不同的 Handler 進(jìn)行業(yè)務(wù)處理;
5)Handler 完成業(yè)務(wù)處理。
可以看出 Proactor 和 Reactor 的區(qū)別:
1)Reactor 是在事件發(fā)生時(shí)就通知事先注冊(cè)的事件(讀寫(xiě)在應(yīng)用程序線(xiàn)程中處理完成);
2)Proactor 是在事件發(fā)生時(shí)基于異步 I/O 完成讀寫(xiě)操作(由內(nèi)核完成),待 I/O 操作完成后才回調(diào)應(yīng)用程序的處理器來(lái)進(jìn)行業(yè)務(wù)處理。
理論上 Proactor 比 Reactor 效率更高,異步 I/O 更加充分發(fā)揮 DMA(Direct Memory Access,直接內(nèi)存存取)的優(yōu)勢(shì)。
但是Proactor有如下缺點(diǎn):?
1)編程復(fù)雜性,由于異步操作流程的事件的初始化和事件完成在時(shí)間和空間上都是相互分離的,因此開(kāi)發(fā)異步應(yīng)用程序更加復(fù)雜。應(yīng)用程序還可能因?yàn)榉聪虻牧骺囟兊酶与y以 Debug;
2)內(nèi)存使用,緩沖區(qū)在讀或?qū)懖僮鞯臅r(shí)間段內(nèi)必須保持住,可能造成持續(xù)的不確定性,并且每個(gè)并發(fā)操作都要求有獨(dú)立的緩存,相比 Reactor 模式,在 Socket 已經(jīng)準(zhǔn)備好讀或?qū)懬?,是不要求開(kāi)辟緩存的;
3)操作系統(tǒng)支持,Windows 下通過(guò) IOCP 實(shí)現(xiàn)了真正的異步 I/O,而在 Linux 系統(tǒng)下,Linux 2.6 才引入,目前異步 I/O 還不完善。
因此在 Linux 下實(shí)現(xiàn)高并發(fā)網(wǎng)絡(luò)編程都是以 Reactor 模型為主。
參考:http://www.52im.net/forum.php
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/77417.html
摘要:缺點(diǎn)每個(gè)連接需要獨(dú)立的進(jìn)程線(xiàn)程單獨(dú)處理,當(dāng)并發(fā)請(qǐng)求量大時(shí)為了維護(hù)程序,內(nèi)存線(xiàn)程切換開(kāi)銷(xiāo)較大,這種模型在實(shí)際生產(chǎn)中很少使用。而在系統(tǒng)下,才引入,目前并不完善,因此在下實(shí)現(xiàn)高并發(fā)網(wǎng)絡(luò)編程時(shí)都是以復(fù)用模型模式為主。 思維導(dǎo)圖 showImg(https://segmentfault.com/img/bVbkrNz?w=1766&h=994); 互聯(lián)網(wǎng)服務(wù)端處理網(wǎng)絡(luò)請(qǐng)求的原理 首先看看一個(gè)典型...
摘要:?jiǎn)栴}任一文件句柄的不成功會(huì)阻塞住整個(gè)應(yīng)用。主要解決的前兩個(gè)問(wèn)題通過(guò)一個(gè)數(shù)組向內(nèi)核傳遞需要關(guān)注的事件消除文件句柄上限,同時(shí)使用不同字段分別標(biāo)注關(guān)注事件和發(fā)生事件,來(lái)避免重復(fù)初始化。問(wèn)題逐個(gè)排查所有文件句柄狀態(tài)效率不高。 C10K問(wèn)題思維導(dǎo)圖 showImg(https://segmentfault.com/img/bVbkrKe?w=1818&h=1276); C10K問(wèn)題出現(xiàn)前期 大家...
摘要:在中一般來(lái)說(shuō)通過(guò)來(lái)創(chuàng)建所需要的線(xiàn)程池,如高并發(fā)原理初探后端掘金閱前熱身為了更加形象的說(shuō)明同步異步阻塞非阻塞,我們以小明去買(mǎi)奶茶為例。 AbstractQueuedSynchronizer 超詳細(xì)原理解析 - 后端 - 掘金今天我們來(lái)研究學(xué)習(xí)一下AbstractQueuedSynchronizer類(lèi)的相關(guān)原理,java.util.concurrent包中很多類(lèi)都依賴(lài)于這個(gè)類(lèi)所提供的隊(duì)列式...
摘要:在中一般來(lái)說(shuō)通過(guò)來(lái)創(chuàng)建所需要的線(xiàn)程池,如高并發(fā)原理初探后端掘金閱前熱身為了更加形象的說(shuō)明同步異步阻塞非阻塞,我們以小明去買(mǎi)奶茶為例。 AbstractQueuedSynchronizer 超詳細(xì)原理解析 - 后端 - 掘金今天我們來(lái)研究學(xué)習(xí)一下AbstractQueuedSynchronizer類(lèi)的相關(guān)原理,java.util.concurrent包中很多類(lèi)都依賴(lài)于這個(gè)類(lèi)所提供的隊(duì)列式...
摘要:表示的是兩個(gè),當(dāng)其中任意一個(gè)計(jì)算完并發(fā)編程之是線(xiàn)程安全并且高效的,在并發(fā)編程中經(jīng)??梢?jiàn)它的使用,在開(kāi)始分析它的高并發(fā)實(shí)現(xiàn)機(jī)制前,先講講廢話(huà),看看它是如何被引入的。電商秒殺和搶購(gòu),是兩個(gè)比較典型的互聯(lián)網(wǎng)高并發(fā)場(chǎng)景。 干貨:深度剖析分布式搜索引擎設(shè)計(jì) 分布式,高可用,和機(jī)器學(xué)習(xí)一樣,最近幾年被提及得最多的名詞,聽(tīng)名字多牛逼,來(lái),我們一步一步來(lái)?yè)羝魄皟蓚€(gè)名詞,今天我們首先來(lái)說(shuō)說(shuō)分布式。 探究...
閱讀 798·2021-10-09 09:44
閱讀 703·2019-08-30 13:55
閱讀 3161·2019-08-29 15:07
閱讀 3227·2019-08-29 13:09
閱讀 2419·2019-08-29 11:10
閱讀 1296·2019-08-26 14:05
閱讀 3604·2019-08-26 13:57
閱讀 2211·2019-08-23 16:42