簡體   English   中英

Spring + Jetty:優雅的關機

[英]Spring + Jetty: graceful shutdown

目標:使用嵌入式Jetty的Spring Web應用程序,我想優雅地關閉/重新啟動應用程序。
這是EmbeddedServletContainerFactory bean(如果需要,我將添加省略的代碼):

@Bean
public EmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
    JettyEmbeddedServletContainerFactory factory = new JettyEmbeddedServletContainerFactory();
    factory.addServerCustomizers(server -> {

        server.setStopAtShutdown(false);

        /*
         * StatisticsHandler has to be added for graceful shutdown to work (see
         * https://github.com/eclipse/jetty.project/issues/1549#issuecomment-301102535)
         */
        StatisticsHandler statisticsHandler = new StatisticsHandler();
        statisticsHandler.setHandler(server.getHandler());
        server.setHandler(statisticsHandler);
    });
    return factory;
}

這是我們的關機信號處理程序:

@Component
public class ShutdownSignalHandler {

    @Value("${shutdown.signalType:TERM}")
    private String signal;

    @Autowired
    private ConfigurableApplicationContext context;

    @Autowired
    private Server jetty; 

    @PostConstruct
    public void init() {
        Signal.handle(new Signal(signal), this::signalHandler);
    }

    private void signalHandler(Signal signal) {
        jetty.stop();
        context.close();
    }
}

問題:具有上述配置,每次通過TERM信號重啟應用程序時,我都會在apache_access日志中看到很多503條目(幾乎所有這些jetty.stop都在執行jetty.stop發生)。
知道它是如何/為什么發生以及解決方案是什么?

為什么/如何發生? 這是Jetty的默認行為:首先,Jetty關閉網絡連接器以停止接受新連接,然后等待活動請求進行處理。 但問題是新的請求可能會通過已建立的連接(在關閉進程啟動之前連接的連接)發送給Jetty。
解決方案:通過打開的連接發送新請求的重試響應。 我們定制了StatisticsHandler以便在停止過程中而不是使用503處理請求時,它使用307 Connection: close, Location: <original-url>來處理它們。

更新:我們所做的是更改StatisticsHandler類的handle方法的實現(查找Change this line!注釋):

@Override
public void handle(String path, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
    ...
    try
    {
        Handler handler = getHandler();
        if (handler!=null && _shutdown.get()==null && isStarted())
            handler.handle(path, baseRequest, request, response);
        else if (baseRequest.isHandled())
        {
            if (_wrapWarning.compareAndSet(false,true))
                LOG.warn("Bad statistics configuration. Latencies will be incorrect in {}",this);
        }
        else
        {
            baseRequest.setHandled(true);
            response.sendError(HttpStatus.SERVICE_UNAVAILABLE_503); // Change this line!
        }
    }
    finally
    {
        ...
    }
}

503服務不可用

在將請求代理到servlet容器時,Apache無法獲得響應,因為在代理配置中指定的host:port上沒有監聽servlet容器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM