Netty 4.1中的新变化和注意点

jopen 9年前
 

本文翻译自官方文档 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(..)

ChannelChannelHandlerContext 实现了 AttributeMap 接口, 允许用户附加一个或者多个属性在它们上. 有时候用户迷惑的是[ ChannelChannelHandlerContext 用户自己的属性存储. 例如,即使你通过 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 可用性

EmbeddedChannelreadInbound()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, 然后关闭连接.

ChunkedInputChunkedWriteHandler

ChunkedInput 有两个新的方法; progress()length() 返回数据传输的进度以及流的程度. ChunkedWriteHandler 使用这个信息通知 ChannelProgressiveFutureListener .

SnappyFramedEncoderSnappyFramedDecoder

这两个类被改名为 SnappyFrameEncoder and SnappyFrameDecoder . T老的类被标记为弃用, 实际上它们是新的类的子类.