конвейеры netty не освобождаются из памяти - PullRequest
1 голос
/ 03 марта 2012

У меня большой объем нетти-сервера, который продолжает потреблять память.Используя 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 - частный статический таймер 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 - базовый обработчик простоя, указанный в примерах, за исключениемиспользуя «все».Это не выполняется так часто.Время ожидания составляет 500 миллисекунд.(примерно 1/2 секунды).Обработчик бездействия вызывает закрытие на канале.HttpClose () - это простое закрытие канала для всего, что делает его там на тот случай, если обработчик не обработает его.Он выполняется очень нерегулярно.

После того как я отправил ответ в свой обработчик (полученный из SimpleChannelUpstreamHandler), я закрываю канал независимо от настройки keepalive.Я подтвердил, что закрываю каналы, добавив прослушиватель к каналам ChannelFuture, возвращаемым функцией close (), и значение isSuccess в прослушивателе равно true.

Некоторые примеры из вывода jmap (столбцы: rank, количество экземпляров, размер в байтах, имя класса):

 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 Ответ

2 голосов
/ 03 марта 2012

Если в вашем приложении нет ссылки на Channel, ChannelPipeline, ChannelHandlerContext, они должны стать недоступными, как только соединение будет закрыто. Пожалуйста, проверьте, не содержит ли ваше приложение ссылку на один из них. Иногда анонимный класс является хорошим подозреваемым, но точный ответ не будет возможен с файлом дампа кучи.

...