Как полностью отключить сервер undertow, содержащий сервлеты

Я создал сервер undertow с развертыванием сервлета, следуя методам, описанным в документации здесь:

http://undertow.io/documentation/servlet/deployment.html

Сейчас я пытаюсь остановить сервер и приложение в сервлете.

Вызов 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();
    }
}

person dom_watson    schedule 12.04.2015    source источник


Ответы (2)


Вы сохраняете то, что известно как сильная ссылка на компоненты Undertow и все, на что они также напрямую ссылаются. Ссылки хранятся в следующих полях:

private DeploymentManager deploymentManager;
private Undertow          undertowServer;
private DeploymentInfo    servletInfo;

Это не столько проблема с Undertow, сколько с тем, как работает JVM. Сборщик мусора начинает с набора корней (представьте себе, что это потоки в JVM) и проходит по всем ссылкам на другие объекты. После завершения обхода все недоступные объекты возвращаются. Это логическое видение всего процесса. Время сбора зависит от JVM, а также от поколений. Следующий код удалит ссылки на компоненты, если вы поместите их в метод #shutdown():

   deploymentManager = null;
   undertowServer = null;
   servletInfo = null;

Примечание: как только вы это сделаете, вы не сможете перезапустить.

person Mark    schedule 12.04.2015
comment
После некоторого дальнейшего рефакторинга, чтобы изменить способ создания сервера с учетом вашего ответа, я теперь кое-что понимаю в этом. Похоже, вы попали в точку, спасибо. - person dom_watson; 13.04.2015

Поместите порт администратора (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);
    }
}
person Matthew Ong    schedule 28.05.2015