tomcat长连接使用
新建AsyncContext ,然后将AsyncContext 放入到线程池中执行。
AsyncContext asyncContext = request.startAsync();
asyncContext.addListener(new AppAsyncListener());
asyncContext.setTimeout(timeout);
ThreadPoolExecutor executor = (ThreadPoolExecutor) request
.getServletContext().getAttribute("executor");
executor.execute(new AsyncRequestProcessor(asyncContext, workTime));
启动分析
1 获取AsyncContext
org.apache.catalina.connector.Request#startAsync()
public AsyncContext startAsync(ServletRequest request,
ServletResponse response) {
if (!isAsyncSupported()) {
throw new IllegalStateException(sm.getString("request.asyncNotSupported"));
}
if (asyncContext == null) {
// 新建asyncContext
asyncContext = new AsyncContextImpl(this);
}
//设置启动状态
asyncContext.setStarted(getContext(), request, response,
request==getRequest() && response==getResponse().getResponse());
// 设置默认超时时间
asyncContext.setTimeout(getConnector().getAsyncTimeout());
return asyncContext;
}
org.apache.catalina.core.AsyncContextImpl#setStarted
public void setStarted(Context context, ServletRequest request,
ServletResponse response, boolean originalRequestResponse) {
synchronized (asyncContextLock) {
// 重点关注
this.request.getCoyoteRequest().action(
ActionCode.ASYNC_START, this);
this.context = context;
this.servletRequest = request;
this.servletResponse = response;
this.hasOriginalRequestAndResponse = originalRequestResponse;
this.event = new AsyncEvent(this, request, response);
// 触发注册的Listener
List listenersCopy = new ArrayList<>();
listenersCopy.addAll(listeners);
listeners.clear();
for (AsyncListenerWrapper listener : listenersCopy) {
try {
listener.fireOnStartAsync(event);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.warn("onStartAsync() failed for listener of type [" +
listener.getClass().getName() + "]", t);
}
}
}
}
设置异步状态
org.apache.coyote.http11.Http11Processor#action 845行
// 异步启动
case ASYNC_START: {
//设置异步状态为STARTING
asyncStateMachine.asyncStart((AsyncContextCallback) param);
break;
}
// 异步完成,这个稍后会用到
case ASYNC_COMPLETE: {
clearDispatches();
if (asyncStateMachine.asyncComplete()) {
socketWrapper.processSocket(SocketEvent.OPEN_READ, true);
}
break;
}
任务提交后的后续处理
从Valve及FilterChain返回后,进入org.apache.catalina.connector.CoyoteAdapter#service。它最主要作用是不关闭request和response。
if (postParseSuccess) {
//check valves if we support async
request.setAsyncSupported(connector.getService().getContainer().getPipeline().isAsyncSupported());
// Calling the container 去调用Servlet
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
}
//设置异步
if (request.isAsync()) {
async = true;
.....
} else {
request.finishRequest();
response.finishResponse();
}
从CoyoteAdapter返回到Http11Processor
org.apache.coyote.http11.Http11Processor#service
if (getErrorState().isError() || endpoint.isPaused()) {
return SocketState.CLOSED;
} else if (isAsync()) {
// 返回值
return SocketState.LONG;
} else if (isUpgrade()) {
return SocketState.UPGRADING;
} else {
org.apache.coyote.AbstractProtocol.ConnectionHandler#process
if (state == SocketState.LONG) {
// In the middle of processing a request/response. Keep the
// socket associated with the processor. Exact requirements
// depend on type of long poll
longPoll(wrapper, processor);
// 将Processor加入到等待处理队列
if (processor.isAsync()) {
getProtocol().addWaitingProcessor(processor);
}
}
任务完成
任务完成时需要主动调用
asyncContext.complete();
org.apache.catalina.core.AsyncContextImpl#complete
public void complete() {
if (log.isDebugEnabled()) {
logDebug("complete ");
}
check();
//这个和启动的时候类似
request.getCoyoteRequest().action(ActionCode.ASYNC_COMPLETE, null);
}
action触发socketWrapper.processSocket(SocketEvent.OPEN_READ, true);
org.apache.tomcat.util.net.AbstractEndpoint#processSocket
触发processor处理请求
public boolean processSocket(SocketWrapperBase socketWrapper,
SocketEvent event, boolean dispatch) {
try {
if (socketWrapper == null) {
return false;
}
SocketProcessorBase sc = processorCache.pop();
if (sc == null) {
sc = createSocketProcessor(socketWrapper, event);
} else {
sc.reset(socketWrapper, event);
}
Executor executor = getExecutor();
if (dispatch && executor != null) {
executor.execute(sc);
} else {
sc.run();
}
}
超时处理
超时处理线程
org.apache.coyote.AbstractProtocol.AsyncTimeout
while (asyncTimeoutRunning) {
// 每隔一秒扫描一次
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
long now = System.currentTimeMillis();
// 从waitingProcessors去除Processor
for (Processor processor : waitingProcessors) {
processor.timeoutAsync(now);
}
while (endpoint.isPaused() && asyncTimeoutRunning) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
addWaitingProcessor来源
org.apache.coyote.AbstractProtocol#addWaitingProcessor
// 在servlet返回中调用的
public void addWaitingProcessor(Processor processor) {
waitingProcessors.add(processor);
}
判断是否超时
org.apache.coyote.AbstractProcessor#timeoutAsync
public void timeoutAsync(long now) {
if (now < 0) {
doTimeoutAsync();
} else {
long asyncTimeout = getAsyncTimeout();
if (asyncTimeout > 0) {
long asyncStart = asyncStateMachine.getLastAsyncStart();
if ((now - asyncStart) > asyncTimeout) {
//触发超时处理,可以在这一行打断点
doTimeoutAsync();
}
}
}
}
参考
https://zhuanlan.zhihu.com/p/22018499
http://www.importnew.com/8864.html
http://blog.csdn.net/wangyangzhizhou/article/details/53207966