Netty 4中的缓冲区所有权:如何管理缓冲区生命周期?

lac*_*oka 9 netty

我一直在尝试编写一个HTTP客户端来同时获取多个提要(最多1k),这也是学习Netty 4的练习.

我的问题是,如果有一个很好的解释,新的ByteBuf基础设施如何工作?谁"拥有"他们,他们是如何分享的(是吗?)?ChannelPipeline中的每个ChannelHandler都有它自己的ByteBuf吗?

这是一个令我困惑的例子:

我将以下类的实例添加到HTTP客户端管道:

public class MyFilter extends MessageToMessageDecoder<HttpObject> {

    @Override
    protected Object decode(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
        // do some work, but leave msg unchanged
        BufUtil.retain(msg); // Why do I need to call BufUtil.retain(msg) ???
        return msg;
}
Run Code Online (Sandbox Code Playgroud)

如果我没有在msg上调用BufUtil.retain,它似乎得到了GCd,我得到了各种各样的虚假错误.

tru*_*tin 8

HttpContent扩展ReferenceCounted以跟踪它所拥有的缓冲区的生命周期.当ReferenceCounted被实例化,它开始生活refCnt1.如果你打电话retain(),它refCnt会增加. refCnt减少release(),并且底层资源(ByteBuf在这种情况下)一旦被破坏refCnt就被销毁0.

通常,处理程序不需要保留对它完成处理的消息的引用,因为消息通常被丢弃或在处理后转换为其他内容.因此,release()一旦处理程序完成,就必须在消息上调用方法.这通常容易出错,并且很容易导致资源泄漏.

为了避免非常难以追踪的泄漏,一旦处理完消息,就会自动扩展SimpleChannelInboundHandler哪些release()消息.

有关Netty中引用计数的更多信息,请阅读此Wiki页面.它还通过使用Netty的缓冲区泄漏检测机制为您提供有关如何排除缓冲区泄漏的详细信息.

  • @trustin - 我也对所有这些引用计数渗入用户 API 感到困惑和惊讶。API 设计应该“做最不令人惊讶的事情”和“尽可能简单”。也许您可以使用熟悉的 Java 构造来代替:资源,如 try-with-resources。或者只是让消息对象表现得像用户默认的预期,并且只能通过单独的界面获得高性能优化但更复杂的版本;性能并不像快速构建应用程序那么重要,因为它不会泄漏内存。 (2认同)