高性能實踐IO之Reactor模式

      網(wǎng)友投稿 787 2022-05-30

      講到高性能IO繞不開Reactor模式,它是大多數(shù)IO相關(guān)組件如Netty、Redis在使用的IO模式,為什么需要這種模式,它是如何設(shè)計來解決高性能并發(fā)的呢?

      最最原始的網(wǎng)絡(luò)編程思路就是服務(wù)器用一個while循環(huán),不斷監(jiān)聽端口是否有新的套接字連接,如果有,那么就調(diào)用一個處理函數(shù)處理,類似:

      while(true){

      socket = accept();

      handle(socket)

      }

      這種方法的最大問題是無法并發(fā),效率太低,如果當(dāng)前的請求沒有處理完,那么后面的請求只能被阻塞,服務(wù)器的吞吐量太低。

      之后,想到了使用多線程,也就是很經(jīng)典的connection per thread,每一個連接用一個線程處理,類似:

      while(true){

      socket = accept();

      new thread(socket);

      }

      tomcat服務(wù)器的早期版本確實是這樣實現(xiàn)的。多線程的方式確實一定程度上極大地提高了服務(wù)器的吞吐量,因為之前的請求在read阻塞以后,不會影響到后續(xù)的請求,因為他們在不同的線程中。這也是為什么通常會講“一個線程只能對應(yīng)一個socket”的原因。最開始對這句話很不理解,線程中創(chuàng)建多個socket不行嗎?語法上確實可以,但是實際上沒有用,每一個socket都是阻塞的,所以在一個線程里只能處理一個socket,就算accept了多個也沒用,前一個socket被阻塞了,后面的是無法被執(zhí)行到的。

      缺點在于資源要求太高,系統(tǒng)中創(chuàng)建線程是需要比較高的系統(tǒng)資源的,如果連接數(shù)太高,系統(tǒng)無法承受,而且,線程的反復(fù)創(chuàng)建-銷毀也需要代價。

      線程池本身可以緩解線程創(chuàng)建-銷毀的代價,這樣優(yōu)化確實會好很多,不過還是存在一些問題的,就是線程的粒度太大。每一個線程把一次交互的事情全部做了,包括讀取和返回,甚至連接,表面上似乎連接不在線程里,但是如果線程不夠,有了新的連接,也無法得到處理,所以,目前的方案線程里可以看成要做三件事,連接,讀取和寫入。

      線程同步的粒度太大了,限制了吞吐量。應(yīng)該把一次連接的操作分為更細(xì)的粒度或者過程,這些更細(xì)的粒度是更小的線程。整個線程池的數(shù)目會翻倍,但是線程更簡單,任務(wù)更加單一。這其實就是Reactor出現(xiàn)的原因,在Reactor中,這些被拆分的小線程或者子過程對應(yīng)的是handler,每一種handler會出處理一種event。這里會有一個全局的管理者selector,我們需要把channel注冊感興趣的事件,那么這個selector就會不斷在channel上檢測是否有該類型的事件發(fā)生,如果沒有,那么主線程就會被阻塞,否則就會調(diào)用相應(yīng)的事件處理函數(shù)即handler來處理。典型的事件有連接,讀取和寫入,當(dāng)然我們就需要為這些事件分別提供處理器,每一個處理器可以采用線程的方式實現(xiàn)。一個連接來了,顯示被讀取線程或者h(yuǎn)andler處理了,然后再執(zhí)行寫入,那么之前的讀取就可以被后面的請求復(fù)用,吞吐量就提高了。

      【Java】Reactor模式

      幾乎所有的網(wǎng)絡(luò)連接都會經(jīng)過讀請求內(nèi)容——》解碼——》計算處理——》編碼回復(fù)——》回復(fù)的過程,Reactor模式的的演化過程如下:

      這種模型由于IO在阻塞時會一直等待,因此在用戶負(fù)載增加時,性能下降的非常快。

      server導(dǎo)致阻塞的原因:

      1、serversocket的accept方法,阻塞等待client連接,直到client連接成功。

      2、線程從socket inputstream讀入數(shù)據(jù),會進(jìn)入阻塞狀態(tài),直到全部數(shù)據(jù)讀完。

      3、線程向socket outputstream寫入數(shù)據(jù),會阻塞直到全部數(shù)據(jù)寫完。

      改進(jìn):采用基于事件驅(qū)動的設(shè)計,當(dāng)有事件觸發(fā)時,才會調(diào)用處理器進(jìn)行數(shù)據(jù)處理。

      Reactor:負(fù)責(zé)響應(yīng)IO事件,當(dāng)檢測到一個新的事件,將其發(fā)送給相應(yīng)的Handler去處理。

      Handler:負(fù)責(zé)處理非阻塞的行為,標(biāo)識系統(tǒng)管理的資源;同時將handler與事件綁定。

      Reactor為單個線程,需要處理accept連接,同時發(fā)送請求到處理器中。

      由于只有單個線程,所以處理器中的業(yè)務(wù)需要能夠快速處理完。

      改進(jìn):使用多線程處理業(yè)務(wù)邏輯。

      將處理器的執(zhí)行放入線程池,多線程進(jìn)行業(yè)務(wù)處理。但Reactor仍為單個線程。

      繼續(xù)改進(jìn):對于多個CPU的機器,為充分利用系統(tǒng)資源,將Reactor拆分為兩部分。

      Using Multiple Reactors

      mainReactor負(fù)責(zé)監(jiān)聽連接,accept連接給subReactor處理,為什么要單獨分一個Reactor來處理監(jiān)聽呢?因為像TCP這樣需要經(jīng)過3次握手才能建立連接,這個建立連接的過程也是要耗時間和資源的,單獨分一個Reactor來處理,可以提高性能。

      《Scalable IO in Java》筆記

      Reactor模式是什么,有哪些優(yōu)缺點?

      Wikipedia上說:“The reactor design pattern is an event handling pattern for handling service requests delivered concurrently by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to associated request handlers.”。從這個描述中,我們知道Reactor模式首先是事件驅(qū)動的,有一個或多個并發(fā)輸入源,有一個Service Handler,有多個Request Handlers;這個Service Handler會同步的將輸入的請求(Event)多路復(fù)用的分發(fā)給相應(yīng)的Request Handler。如果用圖來表達(dá):

      從結(jié)構(gòu)上,這有點類似生產(chǎn)者消費者模式,即有一個或多個生產(chǎn)者將事件放入一個Queue中,而一個或多個消費者主動的從這個Queue中Poll事件來處理;而Reactor模式則并沒有Queue來做緩沖,每當(dāng)一個Event輸入到Service Handler之后,該Service Handler會主動的根據(jù)不同的Event類型將其分發(fā)給對應(yīng)的Request Handler來處理。

      Reactor模式結(jié)構(gòu)

      在解決了什么是Reactor模式后,我們來看看Reactor模式是由什么模塊構(gòu)成。圖是一種比較簡潔形象的表現(xiàn)方式,因而先上一張圖來表達(dá)各個模塊的名稱和他們之間的關(guān)系:

      高性能實踐IO之Reactor模式

      Handle:即操作系統(tǒng)中的句柄,是對資源在操作系統(tǒng)層面上的一種抽象,它可以是打開的文件、一個連接(Socket)、Timer等。由于Reactor模式一般使用在網(wǎng)絡(luò)編程中,因而這里一般指Socket Handle,即一個網(wǎng)絡(luò)連接(Connection,在Java NIO中的Channel)。這個Channel注冊到Synchronous Event Demultiplexer中,以監(jiān)聽Handle中發(fā)生的事件,對ServerSocketChannnel可以是CONNECT事件,對SocketChannel可以是READ、WRITE、CLOSE事件等。

      Synchronous Event Demultiplexer:阻塞等待一系列的Handle中的事件到來,如果阻塞等待返回,即表示在返回的Handle中可以不阻塞的執(zhí)行返回的事件類型。這個模塊一般使用操作系統(tǒng)的select來實現(xiàn)。在Java NIO中用Selector來封裝,當(dāng)Selector.select()返回時,可以調(diào)用Selector的selectedKeys()方法獲取Set,一個SelectionKey表達(dá)一個有事件發(fā)生的Channel以及該Channel上的事件類型。上圖的“Synchronous Event Demultiplexer ---notifies--> Handle”的流程如果是對的,那內(nèi)部實現(xiàn)應(yīng)該是select()方法在事件到來后會先設(shè)置Handle的狀態(tài),然后返回。不了解內(nèi)部實現(xiàn)機制,因而保留原圖。

      Initiation Dispatcher:用于管理Event Handler,即EventHandler的容器,用以注冊、移除EventHandler等;另外,它還作為Reactor模式的入口調(diào)用Synchronous Event Demultiplexer的select方法以阻塞等待事件返回,當(dāng)阻塞等待返回時,根據(jù)事件發(fā)生的Handle將其分發(fā)給對應(yīng)的Event Handler處理,即回調(diào)EventHandler中的handle_event()方法。

      Event Handler:定義事件處理方法:handle_event(),以供InitiationDispatcher回調(diào)使用。

      Concrete Event Handler:事件EventHandler接口,實現(xiàn)特定事件處理邏輯。

      Reactor模式詳解

      優(yōu)點

      1)響應(yīng)快,不必為單個同步時間所阻塞,雖然Reactor本身依然是同步的;

      2)編程相對簡單,可以最大程度的避免復(fù)雜的多線程及同步問題,并且避免了多線程/進(jìn)程的切換開銷;

      3)可擴展性,可以方便的通過增加Reactor實例個數(shù)來充分利用CPU資源;

      4)可復(fù)用性,reactor框架本身與具體事件處理邏輯無關(guān),具有很高的復(fù)用性;

      缺點

      1)相比傳統(tǒng)的簡單模型,Reactor增加了一定的復(fù)雜性,因而有一定的門檻,并且不易于調(diào)試。

      2)Reactor模式需要底層的Synchronous Event Demultiplexer支持,比如Java中的Selector支持,操作系統(tǒng)的select系統(tǒng)調(diào)用支持,如果要自己實現(xiàn)Synchronous Event Demultiplexer可能不會有那么高效。

      3) Reactor模式在IO讀寫數(shù)據(jù)時還是在同一個線程中實現(xiàn)的,即使使用多個Reactor機制的情況下,那些共享一個Reactor的Channel如果出現(xiàn)一個長時間的數(shù)據(jù)讀寫,會影響這個Reactor中其他Channel的相應(yīng)時間,比如在大文件傳輸時,IO操作就會影響其他Client的相應(yīng)時間,因而對這種操作,使用傳統(tǒng)的Thread-Per-Connection或許是一個更好的選擇,或則此時使用Proactor模式。

      Socket編程 任務(wù)調(diào)度

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:【Java核心面試寶典】Day22、Java數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)面經(jīng)總結(jié)
      下一篇:游戲開發(fā)中的進(jìn)階向量數(shù)學(xué)
      相關(guān)文章
      亚洲av日韩综合一区久热| 亚洲欧美国产国产综合一区 | 久久av无码专区亚洲av桃花岛| 亚洲福利精品电影在线观看| 色窝窝亚洲av网| 精品久久久久久亚洲精品| 亚洲视频中文字幕| 亚洲免费精彩视频在线观看| 亚洲av无码专区国产乱码在线观看| 亚洲精品无码乱码成人| 亚洲精品黄色视频在线观看免费资源| 亚洲AV无码一区二区三区久久精品| 亚洲国产区男人本色在线观看| 亚洲中文字幕无码爆乳app| 日韩亚洲国产综合高清| 亚洲欧美日韩中文字幕一区二区三区| 亚洲人成色777777老人头| 亚洲日日做天天做日日谢| 亚洲精品无码久久久久牙蜜区| 亚洲欧美国产欧美色欲| 亚洲国产成人久久综合| 国产亚洲福利一区二区免费看| 亚洲男人天堂2020| 亚洲乱码中文字幕综合| 久久久久亚洲精品影视| 亚洲欧洲另类春色校园小说| ASS亚洲熟妇毛茸茸PICS| 亚洲国产aⅴ成人精品无吗| 亚洲av综合av一区二区三区| 国产亚洲综合视频| 亚洲午夜久久久影院| 久久亚洲精品成人综合| 亚洲欧洲自拍拍偷午夜色| 亚洲国产精品日韩在线| 亚洲色大成网站www| 亚洲精品无码久久久| 亚洲国产精品SSS在线观看AV| 亚洲精品日韩中文字幕久久久| 亚洲永久在线观看| 婷婷亚洲天堂影院| 亚洲精品tv久久久久|