Java IO的Reactor模式
1. Reactor出現的原因
Reator模式是大多數IO相關元件如Netty、Redis在使用時的IO模式,為什麼需要這種模式,如何設計來解決高效能併發的呢?
最最原始的網路程式設計思路就是伺服器用一個While迴圈,不斷監聽埠是否有新的套接字連線,如果有,就呼叫一個函式處理,類似:
while(true){ socket=accept(); handle(socket) }
這種方法最大的問題是無法併發,效率太低,如果當前的請求沒有處理完,那麼後面的請求只能被阻塞,伺服器的吞吐量太低。
之後想到了使用多執行緒,也就是很經典的connection per thread,每一個連線用一個執行緒處理,類似:
while(true){ socket=accept(); new thread(socket); }
Tomcat伺服器的早期版本也是這麼實現的。多執行緒的方式確實一定程度上極大的提高了伺服器的吞吐量,因為之前的請求在read阻塞以後,不會影響後續的請求,因為他們在不同的執行緒中。這也是為什麼通常會講“一個執行緒只能對應一個socket”的原因。
其實一個執行緒中建立多個socket 語法上是可以的,但是實際上沒用,一個執行緒裡只能處理一個socket,就算accept多個也沒有用,前一個socket被阻塞了,後面的是無法被執行到的。
缺點在於資源要求太高,系統中建立執行緒是需要比較高的系統資源的,如果連線數太高,系統無法承受,而且執行緒的反覆建立-銷燬也需要代價。
執行緒池本身可以緩解執行緒建立-銷燬的代價,這樣優化確實會好很多,就是執行緒的粒度太大。每一個執行緒把一次互動的事情全做了,包括讀取和返回,甚至連線,表面上似乎連線不線上程裡,但是如果執行緒不夠,有了新的連線,也無法得到處理,所以目前方案的執行緒裡可以看成要做三件事:連線/讀取/寫入。
執行緒的粒度太大了,限制了吞吐量。應該把一個執行緒做的3件事拆分為更細的粒度,這些更細的粒度就是更小的執行緒。整個執行緒池的資料會增加很多,但是執行緒更簡單,任務更單一。這其實就是Reactor出現的原因。
以上學習自:高效能IO之Reactor模式 - 時間朋友 - 部落格園
感謝這篇部落格作者,讓我瞭解了Reactor出現的原因。
在Reactor中,這些被拆分的小執行緒或者子過程對應的是handler,每一種handler會處理一種event.
2. 什麼事Reactor模式?
Reactor模式首先是事件驅動的,有一個或多個兵發輸入源,有一個Service Handler,有多個Request Handler,這個Service Handler會同步的將輸入的請求(Event)多路複用的分發給相應的Request Handler.
用圖來表達:
從結構上看,這有點類似生產消費者模式,即有一個或多個生產者將事件放入一個Queue中,而一個或多個消費者主動的從這個Queue中的Poll事件來處理;而Reactor模式則沒有Queue來做緩衝,每當一個Event輸入到Service Handler之後,該Service Handler會主動的根據不同的Event型別將其分發給對應的Request Handler來處理。
第2點學習並摘抄自:http://www.blogjava.net/DLevin/archive/2015/09/02/427045.html