Only release event loops when unused

Resolves #926. Transports can still be alive when the Server shuts down,
but they are using the worker event loops. Only release the worker event
loops when all transport's channels are closed.
This commit is contained in:
Eric Anderson 2015-09-03 15:53:31 -07:00
parent d42559c6af
commit 2a3ae36bd3
1 changed files with 28 additions and 11 deletions

View File

@ -48,6 +48,8 @@ import io.netty.channel.EventLoopGroup;
import io.netty.channel.ServerChannel; import io.netty.channel.ServerChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContext;
import io.netty.util.AbstractReferenceCounted;
import io.netty.util.ReferenceCounted;
import java.io.IOException; import java.io.IOException;
import java.net.SocketAddress; import java.net.SocketAddress;
@ -74,6 +76,7 @@ public class NettyServer implements Server {
private Channel channel; private Channel channel;
private final int flowControlWindow; private final int flowControlWindow;
private final int maxMessageSize; private final int maxMessageSize;
private final ReferenceCounted eventLoopReferenceCounter = new EventLoopReferenceCounter();
NettyServer(SocketAddress address, Class<? extends ServerChannel> channelType, NettyServer(SocketAddress address, Class<? extends ServerChannel> channelType,
@Nullable EventLoopGroup bossGroup, @Nullable EventLoopGroup workerGroup, @Nullable EventLoopGroup bossGroup, @Nullable EventLoopGroup workerGroup,
@ -108,6 +111,12 @@ public class NettyServer implements Server {
b.childHandler(new ChannelInitializer<Channel>() { b.childHandler(new ChannelInitializer<Channel>() {
@Override @Override
public void initChannel(Channel ch) throws Exception { public void initChannel(Channel ch) throws Exception {
eventLoopReferenceCounter.retain();
ch.closeFuture().addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
eventLoopReferenceCounter.release();
}
});
NettyServerTransport transport NettyServerTransport transport
= new NettyServerTransport(ch, sslContext, maxStreamsPerConnection, flowControlWindow, = new NettyServerTransport(ch, sslContext, maxStreamsPerConnection, flowControlWindow,
maxMessageSize); maxMessageSize);
@ -142,7 +151,7 @@ public class NettyServer implements Server {
log.log(Level.WARNING, "Error shutting down server", future.cause()); log.log(Level.WARNING, "Error shutting down server", future.cause());
} }
listener.serverShutdown(); listener.serverShutdown();
releaseSharedGroups(); eventLoopReferenceCounter.release();
} }
}); });
} }
@ -156,7 +165,9 @@ public class NettyServer implements Server {
} }
} }
private void releaseSharedGroups() { class EventLoopReferenceCounter extends AbstractReferenceCounted {
@Override
protected void deallocate() {
try { try {
if (usingSharedBossGroup && bossGroup != null) { if (usingSharedBossGroup && bossGroup != null) {
SharedResourceHolder.release(Utils.DEFAULT_BOSS_EVENT_LOOP_GROUP, bossGroup); SharedResourceHolder.release(Utils.DEFAULT_BOSS_EVENT_LOOP_GROUP, bossGroup);
@ -172,4 +183,10 @@ public class NettyServer implements Server {
} }
} }
} }
@Override
public ReferenceCounted touch(Object hint) {
return this;
}
}
} }