Netty 4.1中的新變化和注意點
本文翻譯自官方文檔 New and noteworthy in 4.1 ,
本文帶你了解Netty 4.0到Netty 4.1的值得注意的改變和新特性.
題外話
盡管我們盡量保持向下兼容,4.1 還是有一些和4.0不完全兼容的地方. 請確保使用新的Netty版本重新編譯你的應用.當你重新編譯你的應用時,你可以能看到一些棄用警告. 請依照修改建議來更正它們, 這樣當你升級到新的版本時會遇到較少的麻煩.
核心改變
Android支持
考慮到:
- 移動設備日益強大
- 自 Ice Cream Sandwich版本后ADK中大部分NIO 和 SSLEngine的問題都被修復
- 用戶很想在移動應用中重用它們的編解碼器和handler
我們決定官方的支持 Android (4.0 及以上版本) .然而,我們并沒有一個為Android提供的測試套件. 如果你發現在Android使用的問題, 請提交一個 issue. 也請考慮貢獻Android的測試代碼作為整個構建過程的一部分.
ChannelHandlerContext.attr(..) == Channel.attr(..)
Channel 和 ChannelHandlerContext 實現了 AttributeMap 接口, 允許用戶附加一個或者多個屬性在它們上. 有時候用戶迷惑的是[ Channel 和 ChannelHandlerContext 用戶自己的屬性存儲. 例如,即使你通過 Channel.attr(KEY_X).set(valueX)
設置一個屬性'KEY_X' , 你也不會通過 ChannelHandlerContext.attr(KEY_X).get()
得到這個屬性, 相反亦然. 這種行為不僅讓人迷惑,而且也浪費內存.
為了解決這個問題, 我們決定為每個Channel在內部只保留一個map. AttributeMap總是使用 AttributeKey 作為它的主鍵. AttributeKey確保主鍵的唯一性, 這樣每個Channel不會有多余一個的attribute map. 由于用戶會將他們自己的主鍵定義為 ChannelHandler 的private static final 字段 , 不會有重復的鍵值的擔憂.
Channel.hasAttr(...)
現在我們可以有效地檢查一個屬性是否存在.
更容易更精確的追蹤buffer leak
先前, 找到buffer泄漏并不容易,泄漏警告不太有幫助. 現在我們有了一個先進的泄漏報告機制,當開銷增加時會被啟用。(We now have an advanced leak reporting mechanism which can be enabled at the cost of increased overhead.)
查看 Reference counted objects 得到更多信息 . 這個特性太重要了,所以也被增加回 4.0.14.
PooledByteBufAllocator
作為默認的buffer allocator
在 4.x 中, 盡管有一些功能局限性, UnpooledByteBufAllocator
曾是默認的allocator. 現在 PooledByteBufAllocator
已經使用了很長一段時間了,而且我們有了先進的buffer泄漏追蹤機制,是時候把它作為默認的buffer allocator了.
現在 PooledByteBufAllocator
是默認的buffer allocator.
全局唯一的 channel ID
每個Channel都有一個唯一的ID,依據一下信息產生:
- MAC 地址 (EUI-48 or EUI-64),
- 進程 ID,
System#currentTimeMillis()
System#nanoTime()
- 一個隨機的 32-bit integer
- 一個順序增加的32-bit integer.
Channe ID可以通過 Channel.id()
方法得到.
更靈活的線程模型
一個新的 ChannelHandlerInvoker 加入, 允許用戶對哪個線程處理handler方法有更多的控制
作為往 ChannelPipeline 中增加 ChannelHandler 時指定 EventExecutor 的替代,指定一個定制的 ChannelHandlerInvoker
實現可以實現更多的控制.
想了解更多的信息,可以參考 commit 132af3a .
EmbeddedChannel 可用性
EmbeddedChannel 的 readInbound()
和 readOutbound()
返回一個 特定類型的參數, 你不必將返回值在轉型, 減少了單元測試代碼的啰嗦.
EmbeddedChannel ch = ...;
// BEFORE:
FullHttpRequest req = (FullHttpRequest) ch.readInbound();
// AFTER:
FullHttpRequest req = ch.readInbound();
能夠使用 Executor
替換 ThreadFactory
一些應用要求用戶運行他們的任務在一個指定的 Executor
. 而4.x在創建event loop時需要用戶指定的是 ThreadFactory
,現在已經用 Executor
替換了.
關于這個改變的更多信息,你可以查看 pull request #1762 .
更友好的類加載器 Class loader friendliness
在容器環境中一些類型如 AttributeKey
對應用程序來說不是太友好,現在沒有這個問題了.
ByteBufAllocator.calculateNewCapacity()
計算可擴展的 ByteBuf
容量的代碼從 AbstractByteBuf
移到 ByteBufAllocator
, 因為 ByteBufAllocator
更方便的知道它管理的buffer的容量計算信息.
新的編解碼和handler
- Binary memcache protocol codec
- Compression codecs
* BZip2 * FastLZ * LZ4 * LZF
- DNS protocol codec
- HAProxy protocol codec
- MQTT protocol codec
- SPDY/3.1 support
- STOMP codec
- SOCKSx codec, 支持版本 4, 4a, 和 5; 查看
socksx
包. - XmlFrameDecoder 允許處理XML文檔流.
- JsonObjectDecoder 允許處理JSON對象流.
- IP filtering handlers
其它編解碼的改變
AsciiString
AsciiString 是一個新的 CharSequence
實現, 包含的字符只占1個字節. 當你處理US-ASCII 或者 ISO-8859-1 字符串時可以節省空間.
例如, HTTP 編解碼器和STOMP編解碼器使用 AsciiString
處理header name. 因為將 AsciiString
編碼到 ByteBuf
中不會有類型轉換的代價,比String類型有更好的性能.
TextHeaders
TextHeaders 提供了一個通用的數據結構,類似Http Header類型的字符串 mutimap . HttpHeaders
也用 TextHeaders
重寫.
MessageAggregator
MessageAggregator 為聚合多個小消息成一個大消息提供了通用的功能,就像 HttpObjectAggregator
實現的那樣. HttpObjectAggregator
使用 MessageAggregator
進行了重寫.
HttpObjectAggregator
更好的處理超出尺寸的消息
在4.0中在客戶端發送消息前沒有辦法拒絕一個超過指定大小的HTTP 消息,即使 100-continue
header已經設置.
4.1中增加了一個可以override方法,叫做 handleOversizedMessage
, 因此用戶可以執行他想要的任務. 默認條件下, 它會返回一個 '413 Request Entity Too Large' response, 然后關閉連接.
ChunkedInput
和 ChunkedWriteHandler
ChunkedInput
有兩個新的方法; progress()
和 length()
返回數據傳輸的進度以及流的程度. ChunkedWriteHandler
使用這個信息通知 ChannelProgressiveFutureListener
.
SnappyFramedEncoder
和 SnappyFramedDecoder
這兩個類被改名為 SnappyFrameEncoder
and SnappyFrameDecoder
. T老的類被標記為棄用, 實際上它們是新的類的子類.