1. 程式人生 > >reactor模式與java nio

reactor模式與java nio

time handlers write syn linu pipe accept 事件處理 schmidt

?? Reactor是由Schmidt, Douglas C提出的一種模式,在高並發server實現中廣泛採用。

改模式採用事件驅動方式,當事件出現時,後調用對應的事件處理代碼(Event Handler)。


這個模式是高並發server的基礎。如nginx和lighttpd。

這兩種對大並發,但每一個請求處理都非常快的場景非常適合。

通常的web訪問就是這個特點。


結構 包含了5個部分,當中handle和Synchronous Event Demultiplexer有OS實現。

Handles: 就是網絡連接(connection),每一個網絡連接都由一個handle表示。

Event(事件)
ACCEPT_EVENT:表示收到連接請求 READ_EVENT:表示收到數據 WRITE_EVENT:表示socket能夠足夠的緩沖區,能夠向其寫入數據。 TIMEOUT_EVENT:超時。

Java NIO不支持這個事件。

SIGNAL_EVENT:信號。

Java NIO不支持這個事件。

CLOSE_EVENT:該socket被關閉。Java NIO不支持這個事件。
Event Handler 事件處理代碼,該對象實例(instance)是和handle關聯的。

每一個Event Handler處理一個handle上的事件。一般的server中至少有兩種事件處理代碼:一個是用來接收連接請求(accept event handler),響應ACCEPT_EVENT。。一個用來處理接受的請求(connection event handler),響應READ_EVENT和WRITE_EVENT。


Synchronous Event Demultiplexer(事件多路分離系統) 該模式的核心,等待handles上的事件。沒有事件出現時,一直堵塞(blocking);當某個(某些)handles上有時間產生時,返回。

這個是實現一般由操作系統提供。如linux的select、poll及epoll等。


Initiation Dispatcher 該對象負責管理Event Handlers(添加,刪除等),當某個handle上有事件出現時,調用對應的 內部使用Synchronous Event Demultiplexer
reactor的論文中給出了實例代碼 Logging_Acceptor是處理接收請求的event handler。

Logging_Handler是處理實際請求的event handler Initiation_Dispatcher::instance是單利模式的Initiation Dispatcher
線程模型 論文中使用的是單線程模型。即一個線程同一時候處理接受請求和處理請求。該模型中。假設每一個請求的處理時間較長。則會影響真個系統的吞吐率。
更為普遍的是使用多線程模型。多線程的基本方式是1:n。

1個線程用來接受連接請求,運行accept event handler。 其它的線程用來處理連接請求,執行connection event handler。n的數量能夠依據執行情況動態調整。假設每一個連接的處理非常快。可能一個線程就夠了。假設處理的時間非常長,則可能一個連接就要有一個線程。
java NIO java nio就是按照reactor模式設計的。

java nio中的主要抽象:

Selector:相當於Synchronous Event Demultiplexer SelectionKey: 相當於event,和一個SocketChannel關聯
SocketChannel:相當於handle java nio中沒有提供initial dispatcher的抽象,這部分功能須要用戶自行實現。 java nio中沒有提供event handler的抽象,這部分功能須要用戶自行實現。
netty 作為API,java nio不會設計的非常全面。僅僅會提供主要的功能。對一般的用戶來說,java nio提供的編程界面還是比較原始(pirmitive),不是非常easy使用。netty是一個網絡編程框架。在java nio的基礎上提供了更高層的抽象。netty的編程比起nio有極大的簡化。

netty中提供了reactor的全部封裝,用戶在使用中僅僅需實現event handler就可以。


netty在event handler上又提供了一層抽象,ChannelPipeline和ChannelHandler。 ChannelPipeline類似於原來的event handler,用來處理連接請求。ChannelPipeline由若幹個ChannelHandler構成,ChannelPipeline會分別調用這些ChannelHandler來處理連接請求。

這樣的設計類似於servlet中的filter chain。

全部的ChannelHandler和在一起,形成了處理鏈路。


netty相同提供了對線程模型的支持,詳細能夠參考netty的文檔。
proactor和reactor的差別 主要差別是在處理連接請求時的方式: reactor: 收到事件後,同步處理。該請求沒有完畢後。該線程不會再去處理其它請求。 proactor:收到事件,異步處理。

該請求會運行異步調用(如異步讀寫文件等),然後該請求調用返回,該線程會繼續運行其它的請求。可是第一個請求並沒有處理完畢,當異步操作完畢時,後有時間通知到第一個請求。完畢處理。proactor的編程會比較復雜。


reactor模式與java nio