Java NIO架構Netty教程(十六)-ServerBootStrap啟動流程源碼分析

來源:互聯網
上載者:User

標籤:pipeline   com   很多   bst   tty   event   start   核心線程   關於   

有一段事件沒有更新文章了,各種原因都有吧。搬家的瑣事,搬家後的安逸呵呵。不過,OneCoder明白,絕不能放鬆。對於Netty的學習,也該稍微深入一點了。

所以,這次OneCoder花了幾天時間,仔細梳理了一下Netty的源碼,總結了一下ServerBootStrap的啟動和任務處理流程,基本涵蓋了Netty的關鍵架構。OneCoder總結了一張流程圖:

該圖是OneCoder通過閱讀Netty源碼,逐漸記錄下來的。基本可以說明Netty服務的啟動流程。這裡在具體講解一下。

首先說明,我們這次順利的流程是基於NioSocketServer的。也就是基於Java NIO Selector的實現方式。在第六講《Java NIO架構Netty教程(六)-Java NIO Selector模式》中,我們已經知道使用Selector的幾個關鍵點,所以這裡我們也重點關注一下,這些點在Netty中是如何使用的。

很多看過Netty源碼的人都說Netty源碼寫的很漂亮。可漂亮在哪呢?Netty通過一個ChannelFactory決定了你當前使用的協議類型(Nio/oio等),比如,OneCoder這裡使用的是NioServerSocket,那麼需要聲明的Factory即為NioServerSocketChannelFactory,聲明了這個Factory,就決定了你使用的Channel,pipeline以及pipeline中,具體處理業務的sink的類型。這種使用方式十分簡潔的,學習曲線很低,切換實現十分容易。

Netty採用的是基於事件的管道式架構設計,事件(Event)在管道(Pipeline)中流轉,交由(通過pipelinesink)相應的處理器(Handler)。這些關鍵元素類型的匹配都是由開始聲明的ChannelFactory決定的。

Netty架構內部的業務也遵循這個流程,Server端綁定連接埠的binder其實也是一個Handler,在構造完Binder後,便要聲明一個Pipeline管道,並賦給建立一個Channel。Netty在newChannel的過程中,相應調用了Java中的ServerSocketChannel.open方法,開啟一個channel。然後觸發fireChannelOpen事件。這個事件的接受是可以複寫的。Binder自身接收了這個事件。在事件的處理中,繼續向下完成具體的連接埠的綁定。對應Selector中的 socketChannel.socket().bind()。然後觸發fireChannelBound事件。預設情況下,該事件無人接受,繼續向下開始構造Boss線程池。我們知道在Netty中Boss線程池是用來接受和分發請求的核心線程池。所以在channel綁定後,必然要啟動Boss線城池,隨時準備接受client發來的請求。在Boss建構函式中,第一次註冊了selector感興趣的事件類型,SelectionKey.OP_ACCEPT。至此,在第六講中介紹的使用Selector的幾個關鍵步驟都體現在Netty中了。在Boss中回啟動一個死迴圈來查詢是否有感興趣的事件發生,對於第一次的用戶端的註冊事件,Boss會將Channel註冊給worker儲存。

這裡補充一下,也是圖中忽略的部分,就是關於worker線程池的初始化時機問題。worker池的構造,在最開始構造ChannelFactory的時候就已經準備好了。在NioServerSocketChannelFactory的建構函式裡,會new一個NioWorkerPool。在NioWorkerPool的基類AbstractNioWorkerPool的建構函式中,會調用OpenSelector方法,其中也開啟了一個selector,並且啟動了worker線程池。<

private void openSelector() { try { selector = Selector.open(); } catch (Throwable t) { throw new ChannelException(&quot;Failed to create a selector.&quot;, t); } // Start the worker thread with the new Selector. boolean success = false; try { DeadLockProofWorker.start(executor, new ThreadRenamingRunnable(this, &quot;New I/O worker #&quot; + id)); success = true; } finally { if (!success) { // Release the Selector if the execution fails. try { selector.close(); } catch (Throwable t) { logger.warn(&quot;Failed to close a selector.&quot;, t); } selector = null; // The method will return to the caller at this point. } } assert selector != null &amp;&amp; selector.isOpen(); }

至此,會分線程啟動AbstractNioWorker中run邏輯。同樣是迴圈處理任務隊列。

processRegisterTaskQueue();processEventQueue();processWriteTaskQueue();processSelectedKeys(selector.selectedKeys());

這樣,設計使事件的接收和處理模組完全解耦。

由此可見,如果你想從nio切換到oio,只需要構造不同的ChannelFacotry即可。果然簡潔優雅。

Java NIO架構Netty教程(十六)-ServerBootStrap啟動流程源碼分析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.