干净地关闭Netty服务器

时间:2014-04-10 09:18:09

标签: memory-leaks netty shutdown jboss-arquillian

你好,目前我正在为Moco框架(https://github.com/dreamhead/moco)开发一个Arquillian扩展。 Moco用于测试RESTful服务,并依赖Netty处理通信。目前Moco正在使用Netty 4.0.18.Final。

但是我在容器内运行Moco(和Netty服务器)时发现了一个问题(Arquillian在容器内运行测试)并且它正确启动但是当取消部署应用程序并且服务器关闭时,下一个日志错误消息被打印:

严重:Web应用程序[/ ba32e781-3a18-44b3-9547-7c26787f3fe7]似乎已经启动了一个名为[pool-2-thread-1]的线程,但未能将其停止。这很可能造成内存泄漏。 abr 08,2014 10:29:06 AM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks 严重:Web应用程序[/ ba32e781-3a18-44b3-9547-7c26787f3fe7]使用[io.netty.util.internal.ThreadLocalRandom $ 2]类型的键创建了一个ThreadLocal(值[io.netty.util.internal.ThreadLocalRandom $ 2 @ 77468cae])和类型[io.netty.util.internal.ThreadLocalRandom]的值(值[io.netty.util.internal.ThreadLocalRandom@6cd3851])但在Web应用程序停止时无法将其删除。线程将随着时间的推移而更新,以避免可能的内存泄漏。

基本上似乎有些线程在服务器尝试关闭时尚未关闭。

从应用程序部署到服务器的Arquillian扩展的角度来看,调用Moco的start方法,在取消部署应用程序之前,调用Moco的stop方法。

但是,让我告诉你Moco的代码:

public int start(final int port, ChannelHandler pipelineFactory) {
    ServerBootstrap bootstrap = new ServerBootstrap();
    bootstrap.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .childHandler(pipelineFactory);

    try {
        future = bootstrap.bind(port).sync();
        SocketAddress socketAddress = future.channel().localAddress();
        address = (InetSocketAddress) socketAddress;
        return address.getPort();
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }

并且stop方法如下:

private void doStop() {
    if (future != null) {
        future.channel().close().syncUninterruptibly();
        future = null;
    }

所以似乎close方法在杀死所有线程之前返回,因此容器会警告你可能存在内存泄漏。

因为我从未使用过Netty,所以我想知道是否有办法确保整个Netty运行时都关闭。

非常感谢你的帮助。

1 个答案:

答案 0 :(得分:0)

我也是Netty的新手(并且不熟悉Arquillian),但基于Netty Docs示例,我相信您可能不会关闭您创建的EventLoopGroup(bossGroup,workerGroup)。来自Netty 4.0 User Guide

  

关闭Netty应用程序通常就像关闭通过shutdownGracefully()创建的所有EventLoopGroup一样简单。它返回一个Future,当EventLoopGroup完全终止并且所有属于该组的频道都已关闭时,它会通知您。

所以你的doStop()方法可能如下所示:

private void doStop() {
    workerGroup.shutdownGracefully();
    bossGroup.shutdownGracefully();
}

Netty文档中的一个示例:Http Static File Server Example