Netty 概述

Netty

Tomcat是基於Http協議的,實質是一個基於http協議的web容器; Netty能經過編程自定義各類協議,由於netty可以經過codec本身來編碼/解碼字節流。
netty的性能不必定比tomcat性能高,tomcat從6.x開始就支持了nio模式,而且後續還有APR模式(一種經過JNI調用apache網絡庫的模式),相比於舊的bio模式,併發性能獲得了很大提升,特別是APR模式。html

爲何netty的性能會高呢?

  1. 基於多路複用模型的IO模型下的Reactor模式(事件驅動IO) , 適用於高併發多鏈接&短而快的IO事件處理 場景。 (多路複用 輪詢每一個socket狀態是內核在進行的, 傳統的NIO是用戶線程
  2. 零拷貝. 開闢堆外內存,IO的處理直接在該內存上處理,減小了BIO模型中用戶態與內核態的數據複製 ----這個與java提供的原生DirectByteBuffer, 在ByteBuffer 的類註釋中有解釋
  3. 提供不少減小拷貝的操做
    1. Unpooled.wrappedBuffer  能夠將 byte[] 、ByteBuf、ByteBuffer等包裝成一個UnpooledDirectByteBuf/UnpooledHeapByteBuf對象(eg. 內部維持了一個byte[],由外部傳入的byte[]直接替換), 進而避免了拷貝操做
    2. CompositeByteBuf.addComponents將多個ByteBuf合併爲一個邏輯上的ByteBuf。
    3. ByteBuf 支持 slice 操做, 所以能夠將 ByteBuf 分解爲多個共享同一個存儲區域的 ByteBuf, 避免了內存的拷貝
    4. 經過 FileRegion 包裝的FileChannel.tranferTo 實現文件傳輸, 能夠直接將文件緩衝區的數據發送到目標 Channel, 避免了傳統經過循環 write 方式致使的內存拷貝問題.

      詳見: http://www.javashuo.com/article/p-pededtnv-bu.html

支持併發高

基於多路複用的NIO(Nonblocking I/O,非阻塞IO)開發的網絡通訊框架,對比於BIO併發性能獲得了很大提升。java

BIO的通訊方式

等待客戶端發數據這個過程是阻塞的,這樣就形成了一個線程只能處理一個請求的狀況,而機器能支持的最大線程數是有限的(linux 的unlimit)。linux

NIO的通訊方式

當一個Socket創建好以後,Thread並不會阻塞去接受這個Socket,而是將這個請求交給Selector,Selector會不斷的去遍歷全部的Socket,一旦有一個Socket創建完成,他會通知Thread,而後Thread處理完數據再返回給客戶端。這樣就能讓一個Thread處理更多的請求了。web

傳輸快

Netty的傳輸快其實也是依賴了NIO的一個特性——零拷貝apache

傳統數據拷貝

Java的內存有堆內存、棧內存和字符串常量池等等,其中堆內存是佔用內存空間最大的一塊,也是Java對象存放的地方,通常數據若是須要從IO讀取到堆內存,中間須要通過Socket緩衝區,也就是說一個數據會被拷貝兩次才能到達他的的終點,若是數據量大,就會形成沒必要要的資源浪費。(數據從網卡到內核空間 -> 內核空間再copy到用戶空間)編程

零拷貝

Netty當須要接收數據的時候,他會在堆內存以外開闢一塊內存,數據就直接從IO讀到了那塊內存(堆外內存)中去,在netty裏面經過ByteBuf能夠直接對這些數據進行直接操做,從而加快了傳輸速度。緩存

封裝好

相對於JDK提供的BIO和NIO實現方式,Netty的封裝更勝一籌。tomcat

源碼解析

幾個重要的概念。網絡

  • Channel 數據傳輸流,與channel相關的概念有如下四個
    • Channel,表示一個鏈接,能夠理解爲每個請求,就是一個Channel。
    • ChannelHandler,核心處理業務就在這裏,用於處理業務請求。
    • ChannelHandlerContext,用於傳輸業務數據。
    • ChannelPipeline,用於保存處理過程須要用到的ChannelHandler和ChannelHandlerContext。
  • ByteBuf 
    一個存儲字節的容器,最大特色就是使用方便,它既有本身的讀索引和寫索引,方便對整段字節緩存進行讀寫,也支持get/set,方便對其中每個字節進行讀寫,數據結構以下圖所示:

    有三種使用模式: --類比於JDK提供的ByteBuffer。
    1. Heap Buffer 堆緩衝區
      堆緩衝區是ByteBuf最經常使用的模式,將數據存儲在堆空間。
    2. Direct Buffer 直接緩衝區
      直接緩衝區是ByteBuf的另一種經常使用模式,內存分配都不發生在堆,jdk1.4引入的nio的ByteBuffer類容許jvm經過本地方法調用分配內存,這樣作有兩個好處
      • 經過免去中間交換的內存拷貝, 提高IO處理速度; 直接緩衝區的內容能夠駐留在垃圾回收掃描的堆區之外。
      • DirectBuffer 在 -XX:MaxDirectMemorySize=xxM大小限制下, 使用 Heap 以外的內存, GC對此」無能爲力」,也就意味着規避了在高負載下頻繁的GC過程對應用線程的中斷影響.
    3. Composite Buffer 複合緩衝區
      複合緩衝區至關於多個不一樣ByteBuf的視圖,這是netty提供的,jdk不提供這樣的功能。
  • Codec
    能完成字節與pojo、pojo與pojo的相互轉換,從而達到自定義協議的目的!!
    在Netty裏面最有名的就是HttpRequestDecoderHttpResponseEncoder了。數據結構

相關文章
相關標籤/搜索