java Jetty:以编程方式停止会导致“无法停止 1 个线程”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4650713/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 07:22:40  来源:igfitidea点击:

Jetty: Stopping programatically causes "1 threads could not be stopped"

javajettyshutdown

提问by Ondra ?i?ka

I have an embedded Jetty 6.1.26 instance. I want to shut it down by HTTP GET sent to /shutdown. So I created a JettyShutdownServlet:

我有一个嵌入式 Jetty 6.1.26 实例。我想通过发送到/shutdown. 所以我创建了一个JettyShutdownServlet

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

 resp.setStatus(202, "Shutting down.");
 resp.setContentType("text/plain");
 ServletOutputStream os = resp.getOutputStream();
 os.println("Shutting down.");
 os.close();
 resp.flushBuffer();

 // Stop the server.
 try {
    log.info("Shutting down the server...");
    server.stop();
 } catch (Exception ex) {
    log.error("Error when stopping Jetty server: "+ex.getMessage(), ex);
 }

However, when I send the request, Jetty does not stop - a thread keeps hanging in org.mortbay.thread.QueuedThreadPoolon the line with this.wait():

但是,当我发送请求时,Jetty 并没有停止 - 一个线程一直挂org.mortbay.thread.QueuedThreadPool在线路上this.wait()

   // We are idle
   // wait for a dispatched job
   synchronized (this)
   {
       if (_job==null)
          this.wait(getMaxIdleTimeMs());
       job=_job;
       _job=null;
   }

...

...

2011-01-10 20:14:20,375 INFO  org.mortbay.log jetty-6.1.26
2011-01-10 20:14:34,756 INFO  org.mortbay.log Started [email protected]:17283
2011-01-10 20:25:40,006 INFO  org.jboss.qa.mavenhoe.MavenHoeApp Shutting down the server...
2011-01-10 20:25:40,006 INFO  org.mortbay.log Graceful shutdown [email protected]:17283
2011-01-10 20:25:40,006 INFO  org.mortbay.log Graceful shutdown org.mortbay.jetty.servlet.Context@1672bbb{/,null}
2011-01-10 20:25:40,006 INFO  org.mortbay.log Graceful shutdown org.mortbay.jetty.webapp.WebAppContext@18d30fb{/jsp,file:/home/ondra/work/Mavenhoe/trunk/target/classes/org/jboss/qa/mavenhoe/web/jsp}
2011-01-10 20:25:43,007 INFO  org.mortbay.log Stopped [email protected]:17283
2011-01-10 20:25:43,009 WARN  org.mortbay.log 1 threads could not be stopped
2011-01-10 20:26:43,010 INFO  org.mortbay.log Shutdown hook executing
2011-01-10 20:26:43,011 INFO  org.mortbay.log Shutdown hook complete

It blocks for exactly one minute, then shuts down. I've added the Graceful shutdown, which should allow me to shut the server down from a servlet; However, it does not work as you can see from the log.

它会阻塞一分钟,然后关闭。我添加了 Graceful shutdown,它应该允许我从 servlet 关闭服务器;但是,正如您从日志中看到的那样,它不起作用。

I've solved it this way:

我是这样解决的:

Server server = new Server( PORT );
server.setGracefulShutdown( 3000 );
server.setStopAtShutdown(true);
...
server.start();

if( server.getThreadPool() instanceof QueuedThreadPool ){
   ((QueuedThreadPool) server.getThreadPool()).setMaxIdleTimeMs( 2000 );
}

setMaxIdleTimeMs()needs to be called after the start(), becase the threadPool is created in start(). However, the threads are already created and waiting, so it only applies after all threads are used at least once.

setMaxIdleTimeMs()需要在 之后调用start(),因为线程池是在 中创建的start()。但是,线程已经创建并等待,因此它仅在所有线程至少使用一次后才适用。

I don't know what else to do except some awfulness like interrupting all threads or System.exit().

除了像中断所有线程或System.exit().

Any ideas? Is there a good way?

有任何想法吗?有什么好办法吗?

回答by Tim

Graceful doesn't do what you think it does - it allows the server to shutdown gracefully, but it does notallow you to shutdown from inside a servlet.

优美没有做什么你认为它-它允许服务器安全关机,但它并没有让你关闭从一个servlet中。

The problem is as described in the mailing-list post you linked to - you're trying to stop the server, while you're still processing a connection inside the server.

问题如您链接到的邮件列表帖子中所述 - 您正在尝试停止服务器,而您仍在处理服务器内部的连接。

You should try changing your servlet's implementation to:

您应该尝试将 servlet 的实现更改为:

// Stop the server.
new Thread()
{
   public void run() {
     try {
        log.info("Shutting down the server...");
        server.stop();
        log.info("Server has stopped.");
     } catch (Exception ex) {
        log.error("Error when stopping Jetty server: "+ex.getMessage(), ex);
     }
   }
}.start();

That way the servlet can finished processing while the server is shutting down, and will not hold up the shutdown process.

这样 servlet 可以在服务器关闭时完成处理,并且不会阻止关闭过程。