Spark使用Netty作爲網絡通住框架,順帶研究了下Netty,把今天成果總結下,後面持續更新。
目錄
架構介紹
Netty由Core、Transport Services、Protocol Support三部分組成。Core主要由三部分組成,分別是Zero-Copy-Capable Rich Byte Buffer、Universal Communication API、Extensible Event Model。
Zero-Copy-Capable Rich Byte Buffer
TCP/IP是一個多層協議,在傳輸過程中傳輸層、物理層會把應用層的數據轉換爲字節,然後按照自身協議的輸出要求選擇合適的字節大小進行拆分或者組合,在拆分或者組合的過程中應用層可能需要多次拷貝數據。數據拷貝對性能存在一定影響,Netty提供的ChannelBuffer是一個零拷貝的Buffer,通過CompositeChannelBuffer和SlicedChannelBuffer兩個類實現了組合、拆分的零拷貝,而New I/O原生的ByteBuffer無法做到這點。(注意:這裏的零拷貝不同於MMAP)
上圖中兩個TCP包文需要組合成一個Http應用層的對象。Netty通過ChannelBuffers(注意:多了一個’s’)把兩個ChannelBuffer組合成一個ChannelBuffer,返回CompositeChannelBuffer。CompositeChannelBuffer僅僅是存儲了多個ChannelBuffer的引用以及它們之間的組合的順序,不會重新開闢新的內存存儲所有的內容。其中SlicedChannelBuffer的思路也一樣。
Universal Communication API
JAVA的Old I/O和New I/O是兩套不同的API,完全不兼容。針對這種情況Netty提供了統一的API。
Exensible Event Model
Reactor模式
Reactor模式是同步非阻塞I/O的多路複用模式,另外有個叫Proactor模式是異步非阻塞I/O多路複用模式。在分享Reactor模式之前我們先來看在I/O操作需要做哪些事情。如圖:外部TCP/IP消息發給了服務器B,消息依次從網卡、內核空間、用戶空間、應用程序。沒有使用MMAP技術情況下,應用程序都是從用戶空間讀取消息。
Richard Stevens的《UNIX Network Programming Volume》提到了5種I/O操作模型,分別爲Blocking I/O、Nonblocking I/O、I/O Multiplexing、Signal Driven I/O、Asynchronous I/O,前面四種都爲同步阻塞I/O或者同步非阻塞I/O,只有AIO爲異步非阻塞I/O。
Reactor(也稱Event Loop)是一個事件處理模式(),一個或者多個輸入類的業務請求併發的被分發到一個叫服務處理程序上,這個服務處理程序就是多路複用器(或者叫多路分發器--Demultiplexer),它分發請求並且以同步的方式路由到相應的請求處理程序。這種模式在併發I/O處理中比較常見。用於同步I/O,核心思想是將所有要處理的I/O事件註冊到一箇中心I/O多路複用器上,主線程阻塞在多路複用器上。注意:複用指的是線程複用,並不是I/O連接複用,多路是泛指多個連接或者多個通道。Reactor模式由四部分構成。
Resources
能夠爲系統提供輸入或者消耗系統輸出的統稱爲資源,在Socket的I/O中資源是Handle,即操作系統中的文件句柄。
Synchronous Event Demultiplexer
使用一個Event Loop阻塞所有資源。當一個Resource在執行了同步阻塞操作後,沒有被阻塞的時候這個Demultiplexer會把資源發送給Dispatcher。JAVA語言中提供的Selector實現了Synchronous Event Demultiplexer。需要注意的Demultiplexer的實現需要操作系統劫持非阻塞I/O操作,如:Linux的select、poll、epoll,Maxos的kqueue。
Dispatcher
負責Request Handler的註冊、註銷,從Demultiplexer調度分配Resource到相應的Request Handler
Request Handler
一個應用程序自定義的請求處理程序模塊
下圖描述了上述四者關係在Reactor模式中相互關係和作用
Reator模式可確保應用處理程序只需要關心業務邏輯即可。Reator模式的擴展能力受限於Request Handler的處理能力和Demultiplexer的實現機制,在Unix中Demultiplexer主要受限於select、epoll、poll的實現。
Netty實現了多個版本的Reator模式,分別爲Reactor單線程模型、Reactor多線程模型、主從Reactor多線程模型。一般情況下Reactor的多線程模型已經夠用了,但在個別場景中,一個NIO線程負責監聽百萬客戶端連接,需要做SLA、login等可能會存在性能問題。主從Reactor多線程模型可解決這些問題。注意:我們也可以理解Reactor多線程模型爲主從模式,主是單線程,從是多線程。
內存模型
內存模型文字解說後續補上,這張圖包含了內存結構、內存分配、內存查找等