Java 泄漏:在此之前未调用ByteBuf.release()';垃圾被收集了。Spring反应器TcpServer

Java 泄漏:在此之前未调用ByteBuf.release()';垃圾被收集了。Spring反应器TcpServer,java,spring,rest,spring-boot,netty,Java,Spring,Rest,Spring Boot,Netty,我使用的是反应堆堆芯[1.1.0.RELEASE],反应堆网络[1.1.0.RELEASE]使用的是netty all[4.0.18.Final],反应堆spring上下文[1.1.0.RELEASE]和spring反应堆TcpServer[spring 4.0.3.RELEASE] 我已经在netty中为健康检查创建了简单的RESTAPI:/health。我遵守了规则 请参见以下代码: import io.netty.handler.codec.http.DefaultFullHttpResp

我使用的是反应堆堆芯[1.1.0.RELEASE],反应堆网络[1.1.0.RELEASE]使用的是netty all[4.0.18.Final],反应堆spring上下文[1.1.0.RELEASE]和spring反应堆TcpServer[spring 4.0.3.RELEASE]

我已经在netty中为健康检查创建了简单的RESTAPI:
/health
。我遵守了规则

请参见以下代码:

import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;

import org.springframework.stereotype.Service;

import reactor.function.Consumer;
import reactor.net.NetChannel;

@Service
public class HealthCheckNettyRestApi{

    public Consumer<FullHttpRequest> getResponse(NetChannel<FullHttpRequest, FullHttpResponse> channel,int portNumber){
        return req -> {
            if (req.getMethod() != HttpMethod.GET) {
                channel.send(badRequest(req.getMethod()
                        + " not supported for this URI"));
            } else {
                DefaultFullHttpResponse resp = new DefaultFullHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
                resp.content().writeBytes("Hello World".getBytes());
                resp.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/plain");
                resp.headers().set(HttpHeaders.Names.CONTENT_LENGTH,resp.content().readableBytes());
                //resp.release();
                channel.send((resp));
            }
        };
    }
}
然后我得到以下堆栈跟踪:

2015-04-22 17:23:21.072] - 16497 ERROR [reactor-tcp-io-22] --- i.n.u.ResourceLeakDetector: LEAK: ByteBuf.release() was not called before it's garbage-collected. Enable advanced leak reporting to find out where the leak occurred. To enable advanced leak reporting, specify the JVM option '-Dio.netty.leakDetectionLevel=advanced' or call ResourceLeakDetector.setLevel()


2015-04-22 23:09:26.354 ERROR 4308 --- [actor-tcp-io-13] io.netty.util.ResourceLeakDetector       : LEAK: ByteBuf.release() was not called before it's garbage-collected.
Recent access records: 0
Created at:
    io.netty.buffer.CompositeByteBuf.<init>(CompositeByteBuf.java:59)
    io.netty.buffer.Unpooled.compositeBuffer(Unpooled.java:355)
    io.netty.handler.codec.http.HttpObjectAggregator.decode(HttpObjectAggregator.java:144)
    io.netty.handler.codec.http.HttpObjectAggregator.decode(HttpObjectAggregator.java:49)
    io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89)
    io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:341)
    io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:327)
    io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:155)
    io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:148)
    io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:341)
    io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:327)
    io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785)
    io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:116)
    io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:494)
    io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:461)
    io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:378)
    io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:350)
    io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
    java.lang.Thread.run(Thread.java:745)

2015-04-22 23:09:55.217  INFO 4308 --- [actor-tcp-io-13] r.n.netty.NettyNetChannelInboundHandler  : [id: 0x260faf6d, /127.0.0.1:50275 => /127.0.0.1:8087] Connection reset by peer
2015-04-22 23:09:55.219 ERROR 4308 --- [actor-tcp-io-13] reactor.core.Reactor                     : Connection reset by peer

java.io.IOException: Connection reset by peer
    at sun.nio.ch.FileDispatcherImpl.read0(Native Method)
    at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39)
    at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
    at sun.nio.ch.IOUtil.read(IOUtil.java:192)
    at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
    at io.netty.buffer.UnpooledUnsafeDirectByteBuf.setBytes(UnpooledUnsafeDirectByteBuf.java:446)
    at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:871)
    at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:224)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:108)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:494)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:461)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:378)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:350)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
    at java.lang.Thread.run(Thread.java:745)
2015-04-22 17:23:21.072]-16497错误[reactor-tcp-io-22]——i.n.u.ResourceLeakDetector:LEAK:ByteBuf.release()在垃圾收集之前未被调用。启用高级泄漏报告以查明泄漏发生的位置。要启用高级泄漏报告,请指定JVM选项“-Dio.netty.leakDetectionLevel=advanced”或调用ResourceLeakDetector.setLevel()
2015-04-22 23:09:26.354错误4308---[actor-tcp-io-13]io.netty.util.ResourceLeakDetector:LEAK:ByteBuf.release()在垃圾收集之前未被调用。
最近访问记录:0
创建于:
io.netty.buffer.CompositeByteBuf.(CompositeByteBuf.java:59)
io.netty.buffer.unmooled.compositeBuffer(unmooled.java:355)
io.netty.handler.codec.http.HttpObjectAggregator.decode(HttpObjectAggregator.java:144)
io.netty.handler.codec.http.HttpObjectAggregator.decode(HttpObjectAggregator.java:49)
io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89)
io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:341)
io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:327)
io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:155)
io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:148)
io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:341)
io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:327)
io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785)
io.netty.channel.nio.AbstractNioByteChannel$niobyteensafe.read(AbstractNioByteChannel.java:116)
io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:494)
io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:461)
io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:378)
io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:350)
io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
run(Thread.java:745)
2015-04-22 23:09:55.217信息4308---[actor-tcp-io-13]r.n.netty.NettyNetChannelInboundHandler:[id:0x260faf6d,/127.0.0.1:50275=>/127.0.0.1:8087]对等方重置连接
2015-04-22 23:09:55.219错误4308---[actor-tcp-io-13]reactor.core.reactor:对等方重置连接
java.io.IOException:对等方重置连接
位于sun.nio.ch.FileDispatcherImpl.read0(本机方法)
位于sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39)
位于sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
位于sun.nio.ch.IOUtil.read(IOUtil.java:192)
在sun.nio.ch.socketchannelmpl.read(socketchannelmpl.java:380)
在io.netty.buffer.unmoledUnsafedirectByteBuf.setBytes(unmoledUnsafedirectByteBuf.java:446)
位于io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:871)
位于io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:224)
位于io.netty.channel.nio.AbstractNioByteChannel$niobyteensafe.read(AbstractNioByteChannel.java:108)
位于io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:494)
位于io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:461)
位于io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:378)
在io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:350)
位于io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
运行(Thread.java:745)
我的分析是:我认为既然我正在将
DefaultFullHttpResponse
转发给Spring实现,Spring API应该注意调用
release()
方法。顺便说一句,我还尝试从我的实现中调用
release()
方法,但仍然收到相同的错误


有人能告诉我这个实现有什么问题吗?

可能值得在Reactor(1.1.6)和Netty(4.0.27.Final)的最新版本中尝试一下,以防它是由于已经存在的错误造成的fixed@AndyWilkinson:我试过使用Reactor(1.1.6)和Netty(4.0.20.Final),但仍然得到相同的错误。有没有办法增加网络版呢。Reactor(1.1.6)将Netty(4.0.20.Final)添加为可传递依赖项。您可能应该在github上针对相应项目提出此问题
wrk -t6 -c100 -d30s --latency 'http://localhost:8087/health'
2015-04-22 17:23:21.072] - 16497 ERROR [reactor-tcp-io-22] --- i.n.u.ResourceLeakDetector: LEAK: ByteBuf.release() was not called before it's garbage-collected. Enable advanced leak reporting to find out where the leak occurred. To enable advanced leak reporting, specify the JVM option '-Dio.netty.leakDetectionLevel=advanced' or call ResourceLeakDetector.setLevel()


2015-04-22 23:09:26.354 ERROR 4308 --- [actor-tcp-io-13] io.netty.util.ResourceLeakDetector       : LEAK: ByteBuf.release() was not called before it's garbage-collected.
Recent access records: 0
Created at:
    io.netty.buffer.CompositeByteBuf.<init>(CompositeByteBuf.java:59)
    io.netty.buffer.Unpooled.compositeBuffer(Unpooled.java:355)
    io.netty.handler.codec.http.HttpObjectAggregator.decode(HttpObjectAggregator.java:144)
    io.netty.handler.codec.http.HttpObjectAggregator.decode(HttpObjectAggregator.java:49)
    io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89)
    io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:341)
    io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:327)
    io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:155)
    io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:148)
    io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:341)
    io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:327)
    io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785)
    io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:116)
    io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:494)
    io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:461)
    io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:378)
    io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:350)
    io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
    java.lang.Thread.run(Thread.java:745)

2015-04-22 23:09:55.217  INFO 4308 --- [actor-tcp-io-13] r.n.netty.NettyNetChannelInboundHandler  : [id: 0x260faf6d, /127.0.0.1:50275 => /127.0.0.1:8087] Connection reset by peer
2015-04-22 23:09:55.219 ERROR 4308 --- [actor-tcp-io-13] reactor.core.Reactor                     : Connection reset by peer

java.io.IOException: Connection reset by peer
    at sun.nio.ch.FileDispatcherImpl.read0(Native Method)
    at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39)
    at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
    at sun.nio.ch.IOUtil.read(IOUtil.java:192)
    at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
    at io.netty.buffer.UnpooledUnsafeDirectByteBuf.setBytes(UnpooledUnsafeDirectByteBuf.java:446)
    at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:871)
    at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:224)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:108)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:494)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:461)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:378)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:350)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
    at java.lang.Thread.run(Thread.java:745)