簡體   English   中英

如何處理Jetty異常 - 長時間運行的HTTP請求超時,但它調用的進程永遠不會終止,Jetty不滿意

[英]How to handle Jetty exception - a long running HTTP request times out, but the process it calls never terminates and Jetty is unhappy

我有一個Jetty服務器處理長時間運行的HTTP請求 - 響應由不同的進程X生成,最后是Jetty請求定期檢查的收集器哈希。

有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)


Jetty繼續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
        }
    }

}

這里的問題不是你對AsyncContext#complete()的調用,而是代碼的總體設計。

Continuations(Servlet異步同樣的事情)設計為異步 使用內部延續超時的while循環不能在這里。 您正在通過執行此操作將異步設計轉換為同步設計。 正確的做法是使用Continuation#addContinuationListener()注冊一個監聽器,並實現onTimeout()方法來適當地處理超時情況。

一旦你的超時邏輯結束,我建議將進程X邏輯移動到AsyncHTTPRequestProcessor類,並從需要使用收集器開始。 在處理過程中,您應該假設當前線程永遠不會超時。 通過執行此操作,您對complete()的調用會產生敏感,您將免於收集器上的並發問題。

在這種情況下,使用try catch塊可能會有所幫助。

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

暫無
暫無

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

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