http 服务器的网内存泄漏.何时发布消息?



除非使用SimpleChannelInboundHandler channelRead0,否则如果不调用ctx.fireChannelRead,应该释放输入数据包。

public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
log.error("receive {}", msg);
if (msg instanceof FullHttpRequest) {            
FullHttpRequest req = (FullHttpRequest) msg;
ReferenceCountUtil.release(msg);
clientChannel.writeAndFlush(new RequestWrapper(req, foo)); 
}
}

clientChannel.writeAndFlush成功时,requestWrapper推入队列。 netty 没有显示LEAK warnings,但如 JVM 内存不足中所述,该项目的旧世代增加,事件与ReferenceCountUtil.release(msg)

  1. 如果 HTTP 输入消息没有发布,为什么官方示例没有显式调用发布?
  2. channelRead中,如果收到的味精被设置在另一个 bean 中,然后这个 bean 被ctx.fireChannelRead传递,我应该像上面的代码一样为这个消息调用 release 吗?
  3. 如果一个新对象由ctx.fireChannelRead(newObject)传递,我应该在下一个处理程序中调用release(newObject)吗?

喜欢这个:

public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.fireChannelRead("hello world");
}
public void channelRead(ChannelHandlerContext ctx, Object msg) {
assert "hello world".equals(msg);
ReferenceCountUtil.release(msg); // is this necessary if it is created in the former handler?
}
  1. 写操作怎么样,我是否也应该为写对象调用释放?

喜欢这个:

@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
ctx.write("bye", promise);
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
assert "bye".equals(msg);
// should I call ReferenceCountUtil.release(msg); ?
ctx.write(“bye bye”, promise);
}

1.也许这是一个错误。老实说,我不知道。但是如果你没有在你的处理程序中调用ctx.fireChannelRead(((中断处理程序的链(,它必须释放obj。或者TailContext将释放 obj。

2.您无法在此处理程序中释放 msg,如果这样做,也许其他上下文会分配在此上下文中使用的 obj。仅当 bean 结束时,才应释放对象;

3.你的新对象没有实现引用计数,那你为什么需要释放这个对象呢?只需返回 false,但在ReferenceCountUtil中什么都不做,如下所示:

public static boolean release(Object msg) {
if (msg instanceof ReferenceCounted) {
return ((ReferenceCounted) msg).release();
}
return false;
}

4.你没有必要释放写入对象,因为netty会在发送对象后释放

经过数小时的实验并调试到源代码中,大约第 4 点:ReferenceCountUtil.refCnt

public static int refCnt(Object msg) {
return msg instanceof ReferenceCounted ? ((ReferenceCounted) msg).refCnt() : -1;
}

因为每个 netty 处理程序都是负责任的链模式,所以write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise)实际上可以有任何对象 msg(沿链传递的参数(。在这种情况下,它只需要手动调用 release:

@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
FullHttpResponse fullHttpResponse = ...
ctx.write(fullHttpResponse, promise);
}

FullHttpResponse的实例化最终调用带有 refCnt 加 1 的ByteBuffer.allocate

如果在以下处理程序中,由于异常或userFiredEvents,则不会通过调用发送此FullHttpResponse

ctx.write(msg, promise);
ctx.flush();

然后FullHttpResponse需要手动释放。最后但并非最不重要的一点是,如果FullHttpResponse发布了 refCnt,它不会发出。从客户端的角度来看,请求挂起。

最新更新