Netty 4.0 HTTP Chunks 内存泄漏?

问题描述 投票:0回答:1

我正在尝试使 HTTP Transfer Encoding Chunked 与 Netty 4.0 一起使用。

到目前为止我已经取得了成功。它适用于小负载。

然后我尝试使用大数据,它开始挂起。

我怀疑我的代码可能有问题,或者可能存在

ByteBuf.copy()
泄漏。

我将代码精简到最低限度,以确保没有其他泄漏源或副作用,并且我最终编写了这个测试。 完整代码在这里。

基本上,当您使用 wget 连接到端口 8888 时,它会发送 1GB 的 0x0。当我连接时,我重现了该问题

wget http://127.0.0.1:8888 -O /dev/null

这是处理程序:

    protected void channelRead0(ChannelHandlerContext ctx, FullHttpMessage msg) throws Exception {
        DefaultHttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
        HttpHeaders.setTransferEncodingChunked(response);
        response.headers().set(CONTENT_TYPE, "application/octet-stream");
        ctx.write(response);
            
        ByteBuf buf = Unpooled.buffer();
        int GIGABYTE = (4 * 1024 * 1024); // multiply 256B = 1GB
        for (int i = 0; i < GIGABYTE; i++) {
            buf.writeBytes(CONTENT_256BYTES_ZEROED);
            ctx.writeAndFlush(new DefaultHttpContent(buf.copy()));
            buf.clear();
           }
           ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT).addListener(ChannelFutureListener.CLOSE);
    }

我的做法有什么问题吗?

编辑:

使用 VisualVM,我发现

ChannelOutboundBuffer
中存在内存泄漏。

Entry[] buffer
不断增长,
addCapacity()
被多次调用。
Entry
数组似乎包含要(或应该)写入线路的缓冲区的副本。

我看到wireshark数据传入...

这是指向 heapdump

的 Dropbox 链接
java memory-leaks garbage-collection heap-memory netty
1个回答
1
投票

我发现我做错了什么。

for
循环无法正常工作,很可能是泄漏的原因。

我尝试了各种方法(请参阅要点链接中的许多修订)。

请参阅撰写本文时的要点版本。

我发现实现我想要做的事情而不发生内存泄漏的最佳方法是扩展InputStream并将其写入上下文(不使用

writeAndFlush()

),将InputStream包装在

writeAndFlush()
中。

io.netty.handler.stream.ChunkedStream

代码以 8K 块的形式向客户端写入 1GB 数据。我能够同时运行 30 个连接,没有内存或挂起问题。

© www.soinside.com 2019 - 2024. All rights reserved.