在上一篇文章中我们主要介绍 tomcat nio 中的服务端事件 SSE,在这里我们主要介绍 tomcat 中的异步。对于异步处理来说,主要包括异步的开启,异步的执行,异步的结束,异步的超时以及整个异步处理的状态流转,本文我们主要介绍异步的开启。
异步的开启:
对于异步的使用,我们一般有如下代码:
public void testAsync(HttpServletRequest request, HttpServletResponse response) {
try{
AsyncContext context = request.startAsync();
context.start(new Runnable(){
@Override
public void run() {
/**
* Do you own logic here in business thread and set final result into response
*/
//Complate asyn thread
context.complete();
}});
}catch(Exception ex){
//Handle exception here
}
}
HttpServletRequest 的 startAsync() 方法开启了我们的异步调用。
开启异步的流程:
对于 request.startAsync() 的源码调用序列图如下:
从 HttpServletRequest 的 startAsync() 方法开始,调用到异步上下文对象的 setStarted() 方法,一直再调用到 AsyncStateMachine 对象的 asyncStart() 方法。对于 HttpServletRequest 对象的 startAsync() 方法如下:
上述逻辑首先判断是否支持异步,不支持则抛异常。
创建异步上下文对象,该上下文对象属于 HttpServletRequest 实例。
通过 getConnector().getAsyncTimeout() 来设置异步超时时间, 对于超时时间源码默认为 30 秒,所以如果我们的异步任务有可能大于 30 秒的时候要注意重新设置超时时间。
调用异步上下文对象的 setStarted() 方法来开启异步,该方法源码如下:
运行异步 listener 的 start 事件函数。
源码分析对于 start 事件是执行不到的,因为此时构建出的异步上下文对象里,里并没有设置 listener ,所以不会执行 start 的事件函数。
通过继续调用之前文章中介绍的 tomcat request action(ActionCode.ASYNC_START,this) 方法,最终会调到 AsyncStateMachine 对象实例的 asyncStart() 方法。
AsyncStateMachine 对象实例的 asyncStart() 方法源码如下:
根据以前文章 AsyncStateMachine 对象实例属于Http11Processor 类,该 processor 用来处理包装底层 socket 的 NioChannel 对象。所以异步请求的所有状态都通过 AsyncStateMachine 保存维护的。
AsyncStateMachine 对象中异步的初始状态为 AsyncState.DISPATCHED,通过开启异步改变其状态为 AsyncState.STARTING。
对于异步开启的总结如下: