在netty中重用bytebuf

dbf*_*dbf 2 netty

我在Netty有一个http服务。对于一组请求,在HTTP正文中仅使用“ {}”即可得到相同的答复。我有个主意是避免为每个这样的请求等创建新的缓冲区,所以我刚刚使用了:

private static final ByteBuf EMPTY_REPLY = Unpooled.copiedBuffer("{}", CharsetUtil.UTF_8);
Run Code Online (Sandbox Code Playgroud)

在我的SimpleChannelInboundHandler中。它只对第一个查询有效,之后我开始有

WARNING: Failed to mark a promise as success because it has failed already: DefaultChannelPromise@48c81b24(failure: io.netty.handler.codec.EncoderException: io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1), unnotified cause:
io.netty.handler.codec.EncoderException: io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1
    at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:106)
    at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:738)
    at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:801)
    at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:814)
    at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:794)
    at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:831)
    at travel.ServerHandler.writeResult(ServerHandler.java:475)
Run Code Online (Sandbox Code Playgroud)

所以看起来缓冲区是在第一次回复后自动释放的。有这样的缓冲区的正确方法是什么?

Fer*_*big 5

共享Netty缓冲区时,您需要遵循基本引用计数的规则,这与基本垃圾收集的简单规则不同。

这些规则基本上可以归结为:

  • 当发送ByteBuf从你的类,服务到家retain()
  • 如果您使用完成了ByteBuf,请致电release()

在大多数情况下,当您在发送完字节缓冲区同时完成使用字节缓冲区时,可以删除这两个调用。

在您的示例内部,将共享写入ByteBuf套接字时,应调用retain()以增加引用计数,因为该对象现在在2个不同的地方使用。

在调用之后.retain(),您仍然需要做一招,那就是.duplicate(),因为这可以防止将读者索引的修改传递给您的基本副本,否则,将导致第一次写入成功的问题,但是在此之后,所有后续操作都将成功进行。写操作将写一个空缓冲区。

  • 除此之外,如果您多次写入相同的缓冲区,还应该在其上调用`duplicate()`,以确保您不修改读取器/写入器索引并共享它们。 (2认同)