如何完全关闭包含 servlet 的 undertow 服务器
How to completely shutdown an undertow server containing servlets
我按照此处文档中的方法创建了一个带有 servlet 部署的 undertow 服务器:
http://undertow.io/documentation/servlet/deployment.html
我现在正试图停止服务器和 servlet 中的应用程序。
调用 server.stop()
使服务器在指定端口不可用,但是当我再次调用 server.start()
时,应用程序立即可用(如果它已停止,则需要一些时间才能恢复)重新启动)。我还可以看到调用 server.stop
时服务器的内存没有被释放。我尝试了各种组合,包括调用 deploymentManager.undeploy()
都具有相同的效果。
我已经在文档中搜索了任何线索,但一无所获。我想知道是否还有其他人有任何线索?以下是当前状态下的源代码(请注意,我不是 Java 开发人员,因此会有很多花哨的地方):
package org.locee;
import io.undertow.Undertow;
import io.undertow.Undertow.Builder;
import io.undertow.Handlers;
import io.undertow.util.Headers;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;
import io.undertow.server.handlers.PathHandler;
import io.undertow.server.HttpHandler;
import static io.undertow.servlet.Servlets.defaultContainer;
import javax.servlet.ServletException;
public class LoceeUndertowServer {
private DeploymentManager deploymentManager;
private Undertow undertowServer;
private DeploymentInfo servletInfo;
private int port;
private String host;
public LoceeUndertowServer( DeploymentInfo servletInfo, int port, String host ) {
this.servletInfo = servletInfo;
this.port = port;
this.host = host;
}
public void start() throws ServletException {
deploymentManager = defaultContainer().addDeployment( servletInfo );
deploymentManager.deploy();
HttpHandler httpHandler = deploymentManager.start();
PathHandler pathHandler = Handlers.path( Handlers.redirect( "/" ) ).addPrefixPath( "/", httpHandler );
Builder builder = Undertow.builder();
builder.addHttpListener( port, host );
builder.setHandler( pathHandler );
undertowServer = builder.build();
undertowServer.start();
}
public void shutdown() throws ServletException {
deploymentManager.undeploy();
defaultContainer().removeDeployment( servletInfo );
undertowServer.stop();
}
public void restart() throws ServletException {
shutdown();
start();
}
}
您保留了所谓的对 Undertow 组件的强引用以及它们也直接引用的任何内容。引用存储在以下字段中:
private DeploymentManager deploymentManager;
private Undertow undertowServer;
private DeploymentInfo servletInfo;
这不是 Undertow 的问题,而是 JVM 的功能问题。垃圾收集器从一组根开始(将它们视为 JVM 上的线程)并遍历对其他对象的所有引用。一旦完成遍历,所有不可访问的对象都会被回收。这是整个过程的逻辑视图。收集时间取决于 JVM 以及代数。如果将组件放在 #shutdown() 方法中,以下代码将删除对组件的引用:
deploymentManager = null;
undertowServer = null;
servletInfo = null;
注意:一旦执行此操作,您将无法重新启动。
设置管理端口(8090,如tomcat):
PathHandler path = Handlers.path()
.addPrefixPath("/quitQuit", new QuitHandler());
Undertow.Builder builder = Undertow.builder()
.setHandler(path)
.addHttpListener(8090, "0.0.0.0");
...
public class QuitHandler implements HttpHandler {
@Override
public void handleRequest(HttpServerExchange hse) throws Exception {
// some log info...
System.exit(0);
}
}
我按照此处文档中的方法创建了一个带有 servlet 部署的 undertow 服务器:
http://undertow.io/documentation/servlet/deployment.html
我现在正试图停止服务器和 servlet 中的应用程序。
调用 server.stop()
使服务器在指定端口不可用,但是当我再次调用 server.start()
时,应用程序立即可用(如果它已停止,则需要一些时间才能恢复)重新启动)。我还可以看到调用 server.stop
时服务器的内存没有被释放。我尝试了各种组合,包括调用 deploymentManager.undeploy()
都具有相同的效果。
我已经在文档中搜索了任何线索,但一无所获。我想知道是否还有其他人有任何线索?以下是当前状态下的源代码(请注意,我不是 Java 开发人员,因此会有很多花哨的地方):
package org.locee;
import io.undertow.Undertow;
import io.undertow.Undertow.Builder;
import io.undertow.Handlers;
import io.undertow.util.Headers;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;
import io.undertow.server.handlers.PathHandler;
import io.undertow.server.HttpHandler;
import static io.undertow.servlet.Servlets.defaultContainer;
import javax.servlet.ServletException;
public class LoceeUndertowServer {
private DeploymentManager deploymentManager;
private Undertow undertowServer;
private DeploymentInfo servletInfo;
private int port;
private String host;
public LoceeUndertowServer( DeploymentInfo servletInfo, int port, String host ) {
this.servletInfo = servletInfo;
this.port = port;
this.host = host;
}
public void start() throws ServletException {
deploymentManager = defaultContainer().addDeployment( servletInfo );
deploymentManager.deploy();
HttpHandler httpHandler = deploymentManager.start();
PathHandler pathHandler = Handlers.path( Handlers.redirect( "/" ) ).addPrefixPath( "/", httpHandler );
Builder builder = Undertow.builder();
builder.addHttpListener( port, host );
builder.setHandler( pathHandler );
undertowServer = builder.build();
undertowServer.start();
}
public void shutdown() throws ServletException {
deploymentManager.undeploy();
defaultContainer().removeDeployment( servletInfo );
undertowServer.stop();
}
public void restart() throws ServletException {
shutdown();
start();
}
}
您保留了所谓的对 Undertow 组件的强引用以及它们也直接引用的任何内容。引用存储在以下字段中:
private DeploymentManager deploymentManager;
private Undertow undertowServer;
private DeploymentInfo servletInfo;
这不是 Undertow 的问题,而是 JVM 的功能问题。垃圾收集器从一组根开始(将它们视为 JVM 上的线程)并遍历对其他对象的所有引用。一旦完成遍历,所有不可访问的对象都会被回收。这是整个过程的逻辑视图。收集时间取决于 JVM 以及代数。如果将组件放在 #shutdown() 方法中,以下代码将删除对组件的引用:
deploymentManager = null;
undertowServer = null;
servletInfo = null;
注意:一旦执行此操作,您将无法重新启动。
设置管理端口(8090,如tomcat):
PathHandler path = Handlers.path()
.addPrefixPath("/quitQuit", new QuitHandler());
Undertow.Builder builder = Undertow.builder()
.setHandler(path)
.addHttpListener(8090, "0.0.0.0");
...
public class QuitHandler implements HttpHandler {
@Override
public void handleRequest(HttpServerExchange hse) throws Exception {
// some log info...
System.exit(0);
}
}