一、java nio介紹
? ? java nio全稱java non-blocking IO是jdk1.4以后java新增的非阻塞io,完全可以替代之前的阻塞io。
? ? 1.原理及實現
? ? ?java nio采用reactor(反應器)模式,使用單線程模擬多線程,節省系統線程創建和線程上下文切換所需要的系統資源消耗。增 加了系統吞吐量。nio包含重要概念 通道、緩沖區、選擇器。
? ?通道和緩沖區(Channels and Buffers):標準的IO基于字節流和字符流進行操作的,而NIO是基于通道(Channel)和緩沖區(Buffer)進行操作,數據總是從通道讀取到緩沖區中,或者從緩沖區寫入到通道中。
????通道類型: FileChannel:從文件中讀寫數據。? ?DatagramChannel:能通過UDP讀寫網絡中的數據。? SocketChannel:能通過TCP讀寫網絡中的數據。ServerSocketChannel:可以監聽新進來的TCP連接,像Web服務器那樣。對每一個新進來的連接都會創建一個 SocketChannel。FileChannel比較特殊,它可以與通道進行數據交互, 不能切換到非阻塞模式,套接字通道可以切換到非阻塞模式;
? ??緩沖區 : 本質上是一塊可以存儲數據的內存,被封裝成了buffer對象而已!緩沖區類型:ByteBuffer、MappedByteBuffer 、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer。
? ? 選擇器:相當于一個觀察者,用來監聽通道感興趣的事件,一個選擇器可以綁定多個通道;
二、tomcat9中的nio使用
? ? tomcat8之后去掉原來tomcat中支持的bio模式。只支持nio(非阻塞io)和apr(操作系統級別的異步io)模式。說明tomcat開發者認為現在nio的性能在大多數情況下已經至少不低于bio(阻塞io)。之前網上有很多測試在連接數小于1000的時候tomcat的nio模式沒有明顯的性能提升,甚至還略低于傳統的bio模式。這是因為nio優化的性能在線程的資源占用和上下文切換上。如果連接數較少,這種優化就無法體現。在大并發,傳統模式需要超多線程的情況下,nio模式的性能才有明顯提高。下面我就來總結下tomcat9中nio的實現和使用。
? ? tomcat9中nio的使用主要邏輯在NioEndpoint這個類中。主要有 Acceptor、Poller、SocketProcessor、Excutor等組件參與。來看下他們是如何來實現連接的接入的吧!
? ? 首先從Connector這個類來說起,這個類是用來處理連接的。
這是這個組件的啟動方法,繼續看下protocolHandler.start()這個方法里面。protocolHandler是具體的協議處理器。這里默認應該是http1.1的協議處理器。
這個方法里面首先啟動了NioEndPoint組件。然后啟動一個超時時間守護線程。這個線程我沒有仔細去看應該是監測異步請求的超時。應該屬于http協議的實現部分,暫不做關注,直接進入endpoint.start()方法。
繼續看下startInternal方法這個方法在具體的實現類中,這里我們看下Nioendpoint的startInternal方法。
看下startAcceptorThreads方法
開始接收請求。那么是如何接受請求的呢。我們進去其中一個AcceptorThreads中看看。我們看下這這個thread中的run方法都干了什么
我們看到,AcceptorThreads中主要是先獲取了一個鏈接,然后調用endpoint的setSocketOptions方法,我們看看setSocketOptions方法里都干了什么。
我們看到setSocketOptions 方法首先包裝了下channel,然后就把channel注冊進了poller里。那poller是如何監聽的channel的呢。我們來看下poller的構建及運行。首先我們看下poller的構建方法。
可以看出來poller只是對java nio包中selector進行了一個包裝。調用poller構造方法時。實際上構造了一個selector.我們再來看看注冊方法執行了什么?
poller的注冊方法只是對socket的channle做了一層封裝,然后就注冊一個事件。所以tomcat 和javanio相似只是包裝了一層哈。