2013-05-13 61 views
4

我一直在尝试使用异步上下文的超时功能。但行为是高度间歇的。有时会发生超时,很多时候不会。我在这里粘贴我的代码。异步上下文不超时

@WebServlet(name = "TestServlet", urlPatterns = {"/test"},asyncSupported = true) 
public class TestServlet extends HttpServlet{ 

private static final long serialVersionUID = 1L; 

private static PriorityBlockingQueue<Runnable> pq = new PriorityBlockingQueue<Runnable>(1000); 

private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,1,10, TimeUnit.SECONDS,pq); 

public void service(final ServletRequest servletRequest, final ServletResponse response) 
    throws ServletException, IOException { 
    TestListener listener = new TestListener(); 
    final AsyncContext asyncContext = servletRequest.startAsync(); 
    asyncContext.addListener(listener); 
    asyncContext.setTimeout(100); 
    Handler handler = new Handler(asyncContext); 
    threadPoolExecutor.execute(handler); 
} 
} 

侦听器和处理程序代码包含在下面。

public class TestListener implements AsyncListener { 
public void onComplete(AsyncEvent event) throws IOException { 
    System.out.println("Event completed"); 
} 

public void onError(AsyncEvent event) throws IOException { 
    event.getAsyncContext().complete(); 
} 

public void onStartAsync(AsyncEvent event) throws IOException { 
    // TODO Auto-generated method stub 
} 



public void onTimeout(AsyncEvent event){ 
    System.out.println("Timeout "); 
    event.getAsyncContext().complete(); 
} 
} 

public class Handler implements Runnable { 

private AsyncContext asyncContext; 

public Handler(AsyncContext asyncContext){ 
    this.asyncContext = asyncContext; 
} 
public void run(){ 
    try { 
     long currtime = System.currentTimeMillis(); 
     Thread.sleep(500); 
     System.out.println("slept for " + (System.currentTimeMillis() - currtime)); 
    } catch (InterruptedException e) { 
     System.out.println("Error in thread "); 
    } 

    try{ 
     if(asyncContext != null){ 
      System.out.println("Completing async context " + " timeout is " + asyncContext.getTimeout()); 
      asyncContext.complete(); 
     } 
    }catch (Exception e){ 
     System.out.println("Exception in completing async context "); 
    } 
} 
} 

而且输出是间歇性的。包括同样在这里 -

[[email protected] combinedlogs]$ time curl "http://localhost:9001/mockresponse/test" 

real 0m0.506s 
user 0m0.001s 
sys 0m0.003s 
[[email protected] combinedlogs]$ time curl "http://localhost:9001/mockresponse/test" 

real 0m0.159s 
user 0m0.001s 
sys 0m0.003s 

卡塔利娜日志 -

slept for 500 
Completing async context timeout is 100 
Event completed 

Timeout 
Event completed 
slept for 500 
Exception in completing async context 

我不明白为什么会这样。请帮忙!谢谢你的时间。

PS:将tomcat版本7.0.37

回答

0

尝试增加超时而在睡眠间隔超过1秒。
例如:尝试2秒的超时间隔和5秒的睡眠时间。
servlet容器可能不会检测到持续时间小于1秒的超时。
早些时候,在tomcat中有一些与这种亚秒级超时相关的错误(略微),如this one
我知道你使用的是比那个bug中提到的更高版本的tomcat,它仍然值得尝试。

+0

谢谢您的回复!更高的超时时间和睡眠值确保在每种情况下都超时。我也早点检查过它!但是,当我的超时时间可以从100毫秒到10000毫秒时,它不适合我的目的。我之前也经历过这个bug,所以我决定使用最新版本的tomcat。无论如何,我不认为我可以使用上下文超时,我宁愿使用计时器线程或HashWheeledTimer。谢谢! – 2013-05-14 06:24:16