netty管道没有从内存中释放出来

时间:2012-03-02 22:50:31

标签: nio netty pipeline

我有一个高容量的网络服务器,不断消耗内存。使用jmap,我已经跟踪了管道似乎不断增长和增长的事实(以及nio套接字等)。就像套接字不会断开连接一样。

我对ServerBootstrap的初始化是:

    ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(coreThreads, workThreads, Runtime.getRuntime().availableProcessors()*2));
    bootstrap.setOption("child.keepAlive", false);
    bootstrap.setOption("child.tcpNoDelay", true);
    bootstrap.setPipelineFactory(new HttpChannelPipelineFactory(this, HttpServer.IdleTimer));
    bootstrap.bind(new InetSocketAddress(host, port));

coreThreads和workThreads是java.util.concurrent.Executors.newCachedThreadPool()。

IdleTimer是私有静态Timer IdleTimer = new HashedWheelTimer();

我的管道工厂是:

    ChannelPipeline pipeline = Channels.pipeline();
    pipeline.addLast("idletimer", new HttpIdleHandler(timer));
    pipeline.addLast("decoder", new HttpRequestDecoder());
    pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
    pipeline.addLast("encoder", new HttpResponseEncoder());
    pipeline.addLast("chunkwriter", new ChunkedWriteHandler());
    pipeline.addLast("http.handler" , handler);
    pipeline.addLast("http.closer", new HttpClose());

HttpIdleHandler是示例中给出的基本库存空闲处理程序,除了使用“all”。它不会经常被执行。超时为500毫秒。 (又名1/2秒)。空闲处理程序在通道上调用close。 HttpClose()是一个简单的关闭通道的所有东西,只是处理程序不处理它。它的执行非常不规律。

一旦我在处理程序中发送了响应(从SimpleChannelUpstreamHandler派生),无论keepalive设置如何,我都会关闭通道。我已经通过向close()返回的ChannelFuture通道添加一个监听器来验证我正在关闭通道,并且侦听器中的isSuccess值为true。

jmap输出中的一些示例(列是排名,实例数,大小(以字节为单位),类名称):

 3:        147168        7064064  java.util.HashMap$Entry
 4:         90609        6523848  org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext
 6:         19788        3554584  [Ljava.util.HashMap$Entry;
 8:         49893        3193152  org.jboss.netty.handler.codec.http.HttpHeaders$Entry
11:         11326        2355808  org.jboss.netty.channel.socket.nio.NioAcceptedSocketChannel
24:         11326         996688  org.jboss.netty.handler.codec.http.HttpRequestDecoder
26:         22668         906720  org.jboss.netty.util.internal.LinkedTransferQueue
28:          5165         826400  [Lorg.jboss.netty.handler.codec.http.HttpHeaders$Entry;
30:         11327         815544  org.jboss.netty.channel.AbstractChannel$ChannelCloseFuture
31:         11326         815472  org.jboss.netty.channel.socket.nio.DefaultNioSocketChannelConfig
33:         12107         774848  java.util.HashMap
34:         11351         726464  org.jboss.netty.util.HashedWheelTimer$HashedWheelTimeout
36:         11327         634312  org.jboss.netty.channel.DefaultChannelPipeline
38:         11326         634256  org.jboss.netty.handler.timeout.IdleStateHandler$State
45:         10417         500016  org.jboss.netty.util.internal.LinkedTransferQueue$Node
46:          9661         463728  org.jboss.netty.util.internal.ConcurrentIdentityHashMap$HashEntry
47:         11326         453040  org.jboss.netty.handler.stream.ChunkedWriteHandler
48:         11326         453040  org.jboss.netty.channel.socket.nio.NioSocketChannel$WriteRequestQueue
51:         11326         362432  org.jboss.netty.handler.codec.http.HttpChunkAggregator
52:         11326         362432  org.jboss.netty.util.internal.ThreadLocalBoolean
53:         11293         361376  org.jboss.netty.handler.timeout.IdleStateHandler$AllIdleTimeoutTask
57:          4150         323600  [Lorg.jboss.netty.util.internal.ConcurrentIdentityHashMap$HashEntry;
58:          4976         318464  org.jboss.netty.handler.codec.http.DefaultHttpRequest
64:         11327         271848  org.jboss.netty.channel.SucceededChannelFuture
65:         11326         271824  org.jboss.netty.handler.codec.http.HttpResponseEncoder
67:         11326         271824  org.jboss.netty.channel.socket.nio.NioSocketChannel$WriteTask
73:          5370         214800  org.jboss.netty.channel.UpstreamMessageEvent
74:          5000         200000  org.jboss.netty.channel.AdaptiveReceiveBufferSizePredictor
81:          5165         165280  org.jboss.netty.handler.codec.http.HttpHeaders
84:          1562         149952  org.jboss.netty.handler.codec.http.DefaultCookie
96:          2048          98304  org.jboss.netty.util.internal.ConcurrentIdentityHashMap$Segment
98:          2293          91720  org.jboss.netty.buffer.BigEndianHeapChannelBuffer

我错过了什么?什么线程负责释放它对管道(或套接字?通道?)的引用,以便垃圾收集器收集这个内存?似乎有一些大的哈希表持有它们(我从上面的列表中筛选出几个对哈希表条目的引用)。

1 个答案:

答案 0 :(得分:2)

除非您在应用程序中引用ChannelChannelPipelineChannelHandlerContext,否则一旦连接关闭,它们就会无法访问。请仔细检查您的应用程序是否在某处提及其中一个应用程序。有时匿名类是一个很好的嫌疑人,但使用堆转储文件无法得到准确的答案。