简体   繁体   English

Netty 服务器关闭期间的异常

[英]Exception during Netty server shutdown

I have application running on Tomcat.我有应用程序在 Tomcat 上运行。 I use Netty 4 for websocket handling.我使用 Netty 4 进行 websocket 处理。 Netty server run in ServletContextListener in contextInitialized method and stop in contextDestroyed. Netty 服务器在 ServletContextListener 中的 contextInitialized 方法中运行,并在 contextDestroyed 中停止。

This my class for Netty server:这是我的 Netty 服务器课程:

public class WebSocketServer {

    private final int port;
    private final EventLoopGroup bossGroup;
    private final EventLoopGroup workerGroup;
    private Channel serverChannel;

    public WebSocketServer(int port) {
        this.port = port;
        bossGroup = new NioEventLoopGroup(1);
        workerGroup = new NioEventLoopGroup();
    }

    public void run() throws Exception {
        final ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                .childHandler(new WebSocketServerInitializer());
        serverChannel = b.bind(port).sync().channel();
        System.out.println("Web socket server started at port " + port + '.');
        System.out
                .println("Open your browser and navigate to http://localhost:"
                        + port + '/');
    }

    public void stop() {
        if (serverChannel != null) {
            ChannelFuture chFuture = serverChannel.close();
            chFuture.addListener(new ChannelFutureListener() {

                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    shutdownWorkers();

                }
            });
        } else {
            shutdownWorkers();
        }
    }

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

It's work fine after running, but when I try stop Tomcat I get exception:运行后它工作正常,但是当我尝试停止 Tomcat 时出现异常:

INFO: Illegal access: this web application instance has been stopped already.信息:非法访问:此 Web 应用程序实例已停止。 Could not load io.netty.util.concurrent.DefaultPromise$3.无法加载 io.netty.util.concurrent.DefaultPromise$3。 The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.最终的后续堆栈跟踪是由出于调试目的抛出的错误以及尝试终止导致非法访问的线程引起的,并且没有功能影响。 java.lang.IllegalStateException at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1610) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1569) at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:592) at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:403) at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:139) at java.lang.Thread.run(Thread.java:662) java.lang.IllegalStateException at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1610) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1569) at io.netty.util。 concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:592) at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:403) at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:139) ) 在 java.lang.Thread.run(Thread.java:662)

After Tomcat hangs up. Tomcat挂断后。 What can be reason?什么可以是原因?

I assume you call shutdownWorkers() somewhere from Servlet.destroy() or use some other mechanism that ensures your Server goes down when servlet stops / unloads.我假设您从 Servlet.destroy shutdownWorkers()某处调用shutdownWorkers()或使用其他一些机制来确保您的服务器在 servlet 停止/卸载时关闭。

Then you need to do然后你需要做

void shutdownWorkers() {
    Future fb = trbossGroup.shutdownGracefully();
    Future fw = workerGroup.shutdownGracefully();
    try {
        fb.await();
        fw.await();
    } catch (InterruptedException ignore) {}
}

It is because shutdownGracefully() returns a Future, and, well, without waiting for it to come, you leave things that try to close the connections in very stressful environment.这是因为shutdownGracefully()返回一个Future,而且,不用等待它的到来,你就会在压力很大的环境中尝试关闭连接。 It also makes sense to first initiate all shutdown's and then wait till futures are awailable, this way it all runs in parallel and happens faster.首先启动所有关闭,然后等待期货可用也是有意义的,这样它就可以并行运行并且发生得更快。

It fixed the issue for me.它为我解决了这个问题。 Obviously, you can make it nicer to your system without swallowing InterruptedException and wrapping each call in a nice method and putting reasonable timeout for each await() .显然,您可以让它对您的系统更好,而无需吞下 InterruptedException并将每个调用包装在一个很好的方法中,并为每个await()设置合理的超时。 Nice excercise in general, but in reality most probably you wouldn't care at this point in your code.总体来说不错的练习,但实际上很可能你不会在意你的代码。

Side note: and yes, for WebSockets you will be better off with Tomcat's native, standards-compliant and robust implementation.旁注:是的,对于 WebSockets,使用 Tomcat 的原生、符合标准和健壮的实现会更好。 Netty is awseome for many other things, but would be a wrong tool here. Netty 在许多其他方面都很棒,但在这里是一个错误的工具。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM