[英]Exception during Netty server shutdown
我有应用程序在 Tomcat 上运行。 我使用 Netty 4 进行 websocket 处理。 Netty 服务器在 ServletContextListener 中的 contextInitialized 方法中运行,并在 contextDestroyed 中停止。
这是我的 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();
}
}
运行后它工作正常,但是当我尝试停止 Tomcat 时出现异常:
信息:非法访问:此 Web 应用程序实例已停止。 无法加载 io.netty.util.concurrent.DefaultPromise$3。 最终的后续堆栈跟踪是由出于调试目的抛出的错误以及尝试终止导致非法访问的线程引起的,并且没有功能影响。 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)
Tomcat挂断后。 什么可以是原因?
我假设您从 Servlet.destroy shutdownWorkers()
某处调用shutdownWorkers()
或使用其他一些机制来确保您的服务器在 servlet 停止/卸载时关闭。
然后你需要做
void shutdownWorkers() {
Future fb = trbossGroup.shutdownGracefully();
Future fw = workerGroup.shutdownGracefully();
try {
fb.await();
fw.await();
} catch (InterruptedException ignore) {}
}
这是因为shutdownGracefully()
返回一个Future,而且,不用等待它的到来,你就会在压力很大的环境中尝试关闭连接。 首先启动所有关闭,然后等待期货可用也是有意义的,这样它就可以并行运行并且发生得更快。
它为我解决了这个问题。 显然,您可以让它对您的系统更好,而无需吞下 InterruptedException并将每个调用包装在一个很好的方法中,并为每个await()
设置合理的超时。 总体来说不错的练习,但实际上很可能你不会在意你的代码。
旁注:是的,对于 WebSockets,使用 Tomcat 的原生、符合标准和健壮的实现会更好。 Netty 在许多其他方面都很棒,但在这里是一个错误的工具。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.