目錄
1 Linux I/O模型
2 Linux I/O模型分類
3 Tomcat支持的I/O模型
4 Tomcat I/O模型選型
5 Tomcat NIO實現
6 Tomcat異步IO實現
1 Linux I/O模型
- I/O:在計算機內存和外部設備之間拷貝數據的過程
- 程序通過cpu向外部設備發出讀指令,數據從外部設置拷貝至內存需要一段時間,這段時間cpu是空閑的,此時程序會有兩種選擇:
- 讓出cpu資源,讓其干其他事
- 繼續讓cpu不停地查詢數據是否拷貝完成
- 采用哪種策略就是I/O模型需要解決的事
- 一個進程的地址空間分為用戶空間和內核空間
- 用戶程序只能訪問用戶空間,內核進程可以訪問整個進程空間
- 只有內核才可以直接訪問各種硬件資源,比如磁盤和網卡
- 當cpu從網絡讀取數據時,分為兩個階段
- 數據準備階段:將數據從網卡拷貝到內核空間
- 數據拷貝階段:將數據從內核空間拷貝到用戶空間
- 不同的I/O模型對以上兩個步驟有不同的實現
2 Linux I/O模型分類
- 同步阻塞I/O
- 同步非阻塞I/O
- I/O多路復用
- 信號驅動式I/O
- 異步I/O
- 阻塞或非阻塞是指應用程序在發起I/O操作時,是立即返回還是等待
- 同步或異步是指應用程序在與內核通信時,數據從內核空間到應用空間的拷貝,是由內核主動發起還是由應用程序
java中支持的I/O模型有同步阻塞I/O,I/O多路復用,異步I/O等
3 Tomcat支持的I/O模型
tomcat中支持的I/O模型有:
IO模型 | 描述 |
BIO(BioEndpoint) | 同步阻塞式IO 該模式下每個請求都會占用一個線程,對性能開銷大,不適合高并發場景 但是穩定,適合連接數目小并且固定架構 |
NIO(NioEndpoint) | IO多路復用 tomcat8之后默認采用該IO模型 NIO方式適合連接數多并且連接比較短的架構 |
AIO(Nio2Endpoint) | 異步非阻塞式IO 啟動時執行處理連接方法,此時直接返回 當發生連接事件時,執行回調方法完成連接, 然后執行處理讀事件方法,也是直接返回 當發生讀事件時,執行對應的回調方法 適用于連接數較多且連接事件較長的應用 |
APR(AprEndpoint) | Apache Portable Runtime,是Apache HTTP服務器的支持庫 AprEndpoint是通過JNI調用APR本地庫而實現非阻塞IO的 使用需要編譯安裝APR庫 |
Linux內核沒有很完善地支持異步IO模型
因此JVM并沒有采用原生的Linux異步IO,而是在應用層面通過epoll模擬了異步IO模型
所以在Linux平臺上,Java NIO和Java NIO2底層都是通過epoll來實現的
4 Tomcat I/O模型選型
- IO調優實際上是連接器類型的選擇
- 一般情況默認都是NIO
- 當web應用啟用TLS加密傳輸并且對性能要求極高時,考慮使用APR
- APR是通過openssl來處理TLS握手和加解密的,openssl本身采用c語言開發,并且對TLS通信做了優化,所以性能比java要高的
- 如果tomcat運行在windows平臺,并且http請求的數據量比較大,考慮采用NIO2
- windows從操作系統平面實現了真正意義上的異步IO,如果傳輸的數據量較大時,異步IO的效果就能顯現出來
- 當tomcat運行在linux平臺上時,建議使用NIO,在linux平臺上nio和nio2都是通過epoll來實現的,但是nio更簡單高效
- 指定IO模型時修改Connector標簽的protocol屬性
5 Tomcat NIO實現
- tomcat中Endpoint組件的主要工作就是處理I/O
- NioEndpoint利用java NIO API實現了多路復用I/O模型
- NioEndpoint是基于主從Reactor多線程模型設計的
- LimitLatch是連接控制器,負責控制最大連接數,默認是8192,當連接數達到最大是阻塞線程,直到后續組件處理完一個連接后將連接數減1
- 到達最大連接數后操作系統底層還是會接受客戶端連接,但是用戶層已經不在接收
- Acceptor跑在一個單獨的線程里,在死循環內調用acceptor方法接收新連接,一旦有新的連接請求到來,accept方法返回一個Channel對象,將Channel帝鄉交給Poller去處理
- Poller也跑在單獨的線程,Poller內部維護一個Selector,將Acceptor傳遞過來的Channel注冊到Selector讀事件,一旦發生讀事件,就生成一個SockeProcessor任務對象扔給Executor處理
- Executor就是線程池,負責運行SockeProcessor任務類,SockeProcessor的run方法中會調用Http11Processor來讀取和解析請求數據,Http11Processor是應用層協議的封裝,它負責調用容器獲得響應并將響應通過Channel寫出
6 Tomcat異步IO實現
- NIO和NIO2最大的區別是NIO2時異步的
- 異步不需要應用程序自己去觸發數據從內核空間到用戶空間的拷貝
- NioEndPoint中沒有Poller組件,也就是沒有Selector
- 在異步I/O模式下,Selector的工作交給內核來做了