最近在用tomcat来搞servlet异步化请求,当然异步化下异常处理也很重要,servlet3默认带一个监听器,可以监听onComplete,onError,onStartAsync,onTimeout事件,当然onTimeout可以选择在系统server.xml当中Connector 设置asyncTimeout="100"单位是毫秒,如果不设置,默认就是10秒,当然
AsyncContext asyncContext = request.startAsync();
asyncContext.setTimeout(100);
在代码中也可以去设置,tomcat会以此为准,当然你必须得addListener,
可调试中发现这100毫秒怎么也不会生效,当服务端返回超过100ms,可以请求就是不会报超时,这是为什么呢?看tomcat源码了
找啊找啊找,一切都明了了,原来超时线程在那sleep(1000)呢,因此要得到很短的超时并且能够生效,要么自己搞,要么改tomcat的源码吧
bio && apr
实现
/**
* Async timeout thread
*/
protected class AsyncTimeout implements Runnable {
/**
* The background thread that checks async requests and fires the
* timeout if there has been no activity.
*/
@Override
public void run() {
// Loop until we receive a shutdown command
while (running) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// Ignore
}
long now = System.currentTimeMillis();
Iterator<SocketWrapper<Socket>> sockets =
waitingRequests.iterator();
while (sockets.hasNext()) {
SocketWrapper<Socket> socket = sockets.next();
long access = socket.getLastAccess();
if (socket.getTimeout() > 0 &&
(now-access)>socket.getTimeout()) {
processSocketAsync(socket,SocketStatus.TIMEOUT);
}
}
// Loop if endpoint is paused
while (paused && running) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// Ignore
}
}
}
}
}
nio实现
Poller线程当中,存在
//process timeouts
timeout(keyCount,hasEvents);
因此也是在有新的事件到来,或者selectorTimeout=1000ms超时后,都会去触发
// Async requests with a timeout of 0 or less never timeout
long delta = now - ka.getLastAccess();
long timeout = (ka.getTimeout()==-1)?((long) socketProperties.getSoTimeout()):(ka.getTimeout());
boolean isTimedout = delta > timeout;
if (isTimedout) {
// Prevent subsequent timeouts if the timeout event takes a while to process
ka.access(Long.MAX_VALUE);
processSocket(ka.getChannel(), SocketStatus.TIMEOUT, true);
}