<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                今天我會對 NIO 進行一些補充,在[專欄第 11 講](http://time.geekbang.org/column/article/8369)中,我們初步接觸了 Java 提供的幾種 IO 機制,作為語言基礎類庫,Java 自身的 NIO 設計更偏底層,這本無可厚非,但是對于一線的應用開發者,其復雜性、擴展性等方面,就存在一定的局限了。在基礎 NIO 之上,Netty 構建了更加易用、高性能的網絡框架,廣泛應用于互聯網、游戲、電信等各種領域。 今天我要問你的問題是,對比 Java 標準 NIO 類庫,你知道 Netty 是如何實現更高性能的嗎? ## 典型回答 單獨從性能角度,Netty 在基礎的 NIO 等類庫之上進行了很多改進,例如: * 更加優雅的 Reactor 模式實現、靈活的線程模型、利用 EventLoop 等創新性的機制,可以非常高效地管理成百上千的 Channel。 * 充分利用了 Java 的 Zero-Copy 機制,并且從多種角度,“斤斤計較”般的降低內存分配和回收的開銷。例如,使用池化的 Direct Buffer 等技術,在提高 IO 性能的同時,減少了對象的創建和銷毀;利用反射等技術直接操縱 SelectionKey,使用數組而不是 Java 容器等。 * 使用更多本地代碼。例如,直接利用 JNI 調用 Open SSL 等方式,獲得比 Java 內建 SSL 引擎更好的性能。 * 在通信協議、序列化等其他角度的優化。 總的來說,Netty 并沒有 Java 核心類庫那些強烈的通用性、跨平臺等各種負擔,針對性能等特定目標以及 Linux 等特定環境,采取了一些極致的優化手段。 ## 考點分析 這是一個比較開放的問題,我給出的回答是個概要性的舉例說明。面試官很可能利用這種開放問題作為引子,針對你回答的一個或者多個點,深入探討你在不同層次上的理解程度。 在面試準備中,兼顧整體性的同時,不要忘記選定個別重點進行深入理解掌握,最好是進行源碼層面的深入閱讀和實驗。如果你希望了解更多從性能角度 Netty 在編碼層面的手段,可以參考 Norman 在 Devoxx 上的[分享](https://speakerdeck.com/normanmaurer/writing-highly-performant-network-frameworks-on-the-jvm-a-love-hate-relationship),其中的很多技巧對于實現極致性能的 API 有一定借鑒意義,但在一般的業務開發中要謹慎采用。 雖然提到 Netty,人們會自然地想到高性能,但是 Netty 本身的優勢不僅僅只有這一個方面, 下面我會側重兩個方面: * 對 Netty 進行整體介紹,幫你了解其基本組成。 * 從一個簡單的例子開始,對比在[第 11 講](http://time.geekbang.org/column/article/8369)中基于 IO、NIO 等標準 API 的實例,分析它的技術要點,給你提供一個進一步深入學習的思路。 ## 知識擴展 首先,我們從整體了解一下 Netty。按照官方定義,它是一個異步的、基于事件 Client/Server 的網絡框架,目標是提供一種簡單、快速構建網絡應用的方式,同時保證高吞吐量、低延時、高可靠性。 從設計思路和目的上,Netty 與 Java 自身的 NIO 框架相比有哪些不同呢? 我們知道 Java 的標準類庫,由于其基礎性、通用性的定位,往往過于關注技術模型上的抽象,而不是從一線應用開發者的角度去思考。我曾提到過,引入并發包的一個重要原因就是,應用開發者使用 Thread API 比較痛苦,需要操心的不僅僅是業務邏輯,而且還要自己負責將其映射到 Thread 模型上。Java NIO 的設計也有類似的特點,開發者需要深入掌握線程、IO、網絡等相關概念,學習路徑很長,很容易導致代碼復雜、晦澀,即使是有經驗的工程師,也難以快速地寫出高可靠性的實現。 Netty 的設計強調了 “**Separation Of Concerns**”,通過精巧設計的事件機制,將業務邏輯和無關技術邏輯進行隔離,并通過各種方便的抽象,一定程度上填補了了基礎平臺和業務開發之間的鴻溝,更有利于在應用開發中普及業界的最佳實踐。 另外,**Netty > java.nio + java. net!** 從 API 能力范圍來看,Netty 完全是 Java NIO 框架的一個大大的超集,你可以參考 Netty 官方的模塊劃分。 ![](https://img.kancloud.cn/f5/de/f5de2483afd924b90ea09b656f4fced8_572x329.png) 除了核心的事件機制等,Netty 還額外提供了很多功能,例如: * 從網絡協議的角度,Netty 除了支持傳輸層的 UDP、TCP、[SCTP](https://en.wikipedia.org/wiki/Stream_Control_Transmission_Protocol)協議,也支持 HTTP(s)、WebSocket 等多種應用層協議,它并不是單一協議的 API。 * 在應用中,需要將數據從 Java 對象轉換成為各種應用協議的數據格式,或者進行反向的轉換,Netty 為此提供了一系列擴展的編解碼框架,與應用開發場景無縫銜接,并且性能良好。 * 它擴展了 Java NIO Buffer,提供了自己的 ByteBuf 實現,并且深度支持 Direct Buffer 等技術,甚至 hack 了 Java 內部對 Direct Buffer 的分配和銷毀等。同時,Netty 也提供了更加完善的 Scatter/Gather 機制實現。 可以看到,Netty 的能力范圍大大超過了 Java 核心類庫中的 NIO 等 API,可以說它是一個從應用視角出發的產物。 當然,對于基礎 API 設計,Netty 也有自己獨到的見解,未來 Java NIO API 也可能據此進行一定的改進,如果你有興趣可以參考[JDK-8187540](https://bugs.openjdk.java.net/browse/JDK-8187540)。 接下來,我們一起來看一個入門的代碼實例,看看 Netty 應用到底是什么樣子。 與[第 11 講](http://time.geekbang.org/column/article/8369)類似,同樣是以簡化的 Echo Server 為例,下圖是 Netty 官方提供的 Server 部分,完整用例請點擊[鏈接](http://netty.io/4.1/xref/io/netty/example/echo/package-summary.html)。 ![](https://img.kancloud.cn/97/f1/97f1f65e7277681a9e6da818832c8342_784x738.png) 上面的例子,雖然代碼很短,但已經足夠體現出 Netty 的幾個核心概念,請注意我用紅框標記出的部分: * [ServerBootstrap](https://github.com/netty/netty/blob/2c13f71c733c5778cd359c9148f50e63d1878f7f/transport/src/main/java/io/netty/bootstrap/ServerBootstrap.java),服務器端程序的入口,這是 Netty 為簡化網絡程序配置和關閉等生命周期管理,所引入的 Bootstrapping 機制。我們通常要做的創建 Channel、綁定端口、注冊 Handler 等,都可以通過這個統一的入口,以**Fluent**API 等形式完成,相對簡化了 API 使用。與之相對應,[Bootstrap](https://github.com/netty/netty/blob/2c13f71c733c5778cd359c9148f50e63d1878f7f/transport/src/main/java/io/netty/bootstrap/Bootstrap.java)則是 Client 端的通常入口。 * [Channel](https://github.com/netty/netty/blob/2c13f71c733c5778cd359c9148f50e63d1878f7f/transport/src/main/java/io/netty/channel/Channel.java),作為一個基于 NIO 的擴展框架,Channel 和 Selector 等概念仍然是 Netty 的基礎組件,但是針對應用開發具體需求,提供了相對易用的抽象。 * [EventLoop](https://github.com/netty/netty/blob/2c13f71c733c5778cd359c9148f50e63d1878f7f/transport/src/main/java/io/netty/channel/EventLoop.java),這是 Netty 處理事件的核心機制。例子中使用了 EventLoopGroup。我們在 NIO 中通常要做的幾件事情,如注冊感興趣的事件、調度相應的 Handler 等,都是 EventLoop 負責。 * [ChannelFuture](https://github.com/netty/netty/blob/2c13f71c733c5778cd359c9148f50e63d1878f7f/transport/src/main/java/io/netty/channel/ChannelFuture.java),這是 Netty 實現異步 IO 的基礎之一,保證了同一個 Channel 操作的調用順序。Netty 擴展了 Java 標準的 Future,提供了針對自己場景的特有[Future](https://github.com/netty/netty/blob/eb7f751ba519cbcab47d640cd18757f09d077b55/common/src/main/java/io/netty/util/concurrent/Future.java)定義。 * ChannelHandler,這是應用開發者**放置業務邏輯的主要地方**,也是我上面提到的“Separation Of Concerns”原則的體現。 * [ChannelPipeline](https://github.com/netty/netty/blob/2c13f71c733c5778cd359c9148f50e63d1878f7f/transport/src/main/java/io/netty/channel/ChannelPipeline.java),它是 ChannelHandler 鏈條的容器,每個 Channel 在創建后,自動被分配一個 ChannelPipeline。在上面的示例中,我們通過 ServerBootstrap 注冊了 ChannelInitializer,并且實現了 initChannel 方法,而在該方法中則承擔了向 ChannelPipleline 安裝其他 Handler 的任務。 你可以參考下面的簡化示意圖,忽略 Inbound/OutBound Handler 的細節,理解這幾個基本單元之間的操作流程和對應關系。 ![](https://img.kancloud.cn/77/45/77452800d6567dbf202583a9308421fa_568x533.png) 對比 Java 標準 NIO 的代碼,Netty 提供的相對高層次的封裝,減少了對 Selector 等細節的操縱,而 EventLoop、Pipeline 等機制則簡化了編程模型,開發者不用擔心并發等問題,在一定程度上簡化了應用代碼的開發。最難能可貴的是,這一切并沒有以可靠性、可擴展性為代價,反而將其大幅度提高。 我在[專欄周末福利](http://time.geekbang.org/column/article/12188)中已經推薦了 Norman Maurer 等編寫的《Netty 實戰》(Netty In Action),如果你想系統學習 Netty,它會是個很好的入門參考。針對 Netty 的一些實現原理,很可能成為面試中的考點,例如: * Reactor 模式和 Netty 線程模型。 * Pipelining、EventLoop 等部分的設計實現細節。 * Netty 的內存管理機制、[引用計數](http://netty.io/wiki/reference-counted-objects.html)等特別手段。 * 有的時候面試官也喜歡對比 Java 標準 NIO API,例如,你是否知道 Java NIO 早期版本中的 Epoll[空轉問題](http://www.10tiao.com/html/308/201602/401718035/1.html),以及 Netty 的解決方式等。 對于這些知識點,公開的深入解讀已經有很多了,在學習時希望你不要一開始就被復雜的細節弄暈,可以結合實例,逐步、有針對性的進行學習。我的一個建議是,可以試著畫出相應的示意圖,非常有助于理解并能清晰闡述自己的看法。 今天,從 Netty 性能的問題開始,我概要地介紹了 Netty 框架,并且以 Echo Server 為例,對比了 Netty 和 Java NIO 在設計上的不同。但這些都僅僅是冰山的一角,全面掌握還需要下非常多的功夫。 ## 一課一練 關于今天我們討論的題目你做到心中有數了嗎?今天的思考題是,Netty 的線程模型是什么樣的?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看