如何处理码头例外 - 一个长期运行的HTTP请求超时,但它绝不调用进程终止和Jetty是不爽(How

2019-07-29 23:56发布

我有一个码头服务器处理长期运行的HTTP请求 - 生成的响应通过一个不同的过程X和在集电极散列其中码头请求定期检查结束。

有3种情况:

  1. 过程X的HTTP请求的超时时间段之前结束 - 没问题
  2. 请求的超时时间后过程X完成 - 没有问题
  3. 流程X从未完成 - 下面发生异常

如何同时允许其他两种情况下正常工作,我发现这种情况(3),防止异常?

例外:

2012-06-18 00:13:31.055:WARN:oejut.QueuedThreadPool:
java.lang.IllegalStateException: IDLE,initial
    at org.eclipse.jetty.server.AsyncContinuation.complete(AsyncContinuation.java:569)
    at server.AsyncHTTPRequestProcessor.run(AsyncHTTPRequestProcessor.java:72)
    at org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:1119)
    at org.eclipse.jetty.server.AsyncContinuation$1.run(AsyncContinuation.java:875)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:599)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:534)
    at java.lang.Thread.run(Thread.java:679)


一个HTTP请求的码头延续:

public class AsyncHTTPRequestProcessor implements Runnable {

    private ConcurrentHashMap<String, String> collector;
    private Logger logger;
    private AsyncContext ctx;
    //Defined this here because of strange behaviour when running junit
    //tests and the response json string being empty...
    private String responseStr = null;

    public AsyncHTTPRequestProcessor(AsyncContext _ctx, 
            ConcurrentHashMap<String, String> _collector, Logger _logger) {
        ctx = _ctx;
        collector = _collector;
        logger = _logger;
    }

    @Override
    public void run() {

        logger.info("AsyncContinuation start");

        //if(!((AsyncContinuation)ctx).isInitial()){
        String rid = (String) ctx.getRequest().getAttribute("rid");
        int elapsed = 0;
        if(rid !=null)
        {

            logger.info("AsyncContinuation rid="+rid);

            while(elapsed<ctx.getTimeout())
            {
                if(collector.containsKey(rid)){
                    responseStr = collector.get(rid);
                    collector.remove(rid);

                    logger.info("--->API http request in collector:"+responseStr);
                    ctx.getRequest().setAttribute("status",200);
                    ctx.getRequest().setAttribute("response", responseStr);
                    ctx.getRequest().setAttribute("endTime",System.currentTimeMillis());
                    //ctx.complete();
                    break;
                }
                try {
                    Thread.sleep(10);
                    elapsed+=10;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //}
            logger.info("Collector in async stuff:");
            for(String key:collector.keySet()){
                logger.info(key+"->"+collector.get(key));
            }

            for(Entry<String, String> x:collector.entrySet()){
                logger.info(x.getKey()+"->"+x.getValue());
            }
            ctx.complete(); <---- this line 72
        }
    }

}

Answer 1:

这里的问题是不是你的AsyncContext#完整的(),但该代码的全部测试设计的调用。

延续(对Servlet的异步同样的事情)的设计是异步的 。 while循环,它利用了内部延续超时,一定不会在这里。 您正在改变异步设计,通过这样一个同步。 做正确的事是注册一个使用监听器继续#addContinuationListener()并实现onTimeout()方法来适当地处理超时情况。

一旦超时逻辑是的,我会建议手续X逻辑移到类AsyncHTTPRequestProcessor和需要使用收集的迁出。 在处理过程中,你应该假设当前线程将永远不会超时。 通过这样做,你的电话来完成()使SENS,你会免疫对收集并发麻烦。



Answer 2:

使用try catch块可能有助于在这种情况下。

   try{
      ctx.complete()
   } catch (IllegalStateException e){
      //Handle it the way you prefer.
   }


文章来源: How to handle Jetty exception - a long running HTTP request times out, but the process it calls never terminates and Jetty is unhappy