【问题标题】:Closing Netty server cleanly干净地关闭 Netty 服务器
【发布时间】:2014-04-10 09:18:08
【问题描述】:

您好,目前我正在为 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] 的线程,但未能停止它。这很可能造成内存泄漏。 2014 年 8 月 8 日上午 10:29:06 org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks 严重:Web 应用程序 [/ba32e781-3a18-44b3-9547-7c26787f3fe7] 创建了一个 ThreadLocal,其键类型为 [io.netty.util.internal.ThreadLocalRandom$2](值 [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);
    }

并且停止方法看起来像:

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

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

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

非常感谢您的帮助。

【问题讨论】:

    标签: memory-leaks netty shutdown jboss-arquillian


    【解决方案1】:

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

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

    所以你的 doStop() 方法可能看起来像:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-22
      • 2013-03-29
      • 2010-09-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多