tomcat 异步使用

本文聚焦于Tomcat异步处理的开启,介绍了异步开启的代码,即通过HttpServletRequest的startAsync()方法开启异步调用。详细分析了开启异步的流程,包括源码调用序列、超时时间设置等。指出开启异步不会触发异步listener的start事件,异步状态由AsyncStateMachine对象维护。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于异步处理来说,主要包括异步的开启,异步的执行,异步的结束,异步的超时以及整个异步处理的状态流转,本文我们主要介绍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() 方法如下:

    protected long asyncTimeout = 30000public AsyncContext startAsync(ServletRequest request,ServletResponse response) {    if (!isAsyncSupported()) {        IllegalStateException ise = new IllegalStateException(sm.getString("request.asyncNotSupported"));        log.warn(sm.getString("coyoteRequest.noAsync",StringUtils.join(getNonAsyncClassNames())), ise);        throw ise;    }
        if (asyncContext == null) {        asyncContext = new AsyncContextImpl(this);    }
        asyncContext.setStarted(getContext(), request, response,request==getRequest() && response==getResponse().getResponse());    asyncContext.setTimeout(getConnector().getAsyncTimeout());
        return asyncContext;}
  • 上述逻辑首先判断是否支持异步,不支持则抛异常。

  • 创建异步上下文对象,该上下文对象属于 HttpServletRequest 实例。

  • 通过 getConnector().getAsyncTimeout() 来设置异步超时时间, 对于超时时间源码默认为 30 秒,所以如果我们的异步任务有可能大于 30 秒的时候要注意重新设置超时时间。

  • 调用异步上下文对象的 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;        context.incrementInProgressAsyncCount();        this.servletRequest = request;        this.servletResponse = response;        this.hasOriginalRequestAndResponse = originalRequestResponse;        this.event = new AsyncEvent(this, request, response);
            List<AsyncListenerWrapper> listenersCopy = new ArrayList<>();        listenersCopy.addAll(listeners);        listeners.clear();        for (AsyncListenerWrapper listener : listenersCopy) {            try {                listener.fireOnStartAsync(event);            } catch (Throwable t) {                ExceptionUtils.handleThrowable(t);                log.warn(sm.getString("asyncContextImpl.onStartAsyncError",listener.getClass().getName()), t);            }        }    }}
  • 运行异步 listener 的 start 事件函数。

  • 源码分析对于 start 事件是执行不到的,因为此时构建出的异步上下文对象里,里并没有设置 listener ,所以不会执行 start 的事件函数。

  • AsyncStateMachine 对象实例的 asyncStart() 方法源码如下:

    private volatile AsyncState state = AsyncState.DISPATCHED;synchronized void asyncStart(AsyncContextCallback asyncCtxt) {        if (state == AsyncState.DISPATCHED) {            generation.incrementAndGet();            state = AsyncState.STARTING;            this.asyncCtxt = asyncCtxt;            lastAsyncStart = System.currentTimeMillis();        } else {            throw new IllegalStateException(sm.getString("asyncStateMachine.invalidAsyncState","asyncStart()", state));        }}​​​​​​​
  •  AsyncStateMachine 对象实例属于Http11Processor 类,该 processor 用来处理包装底层 socket 的 NioChannel 对象。所以异步请求的所有状态都通过 AsyncStateMachine 保存维护的。

  • AsyncStateMachine 对象中异步的初始状态为 AsyncState.DISPATCHED,通过开启异步改变其状态为 AsyncState.STARTING。

 

 

对于异步开启的总结如下:

  • 异步调用的开启从 HttpServletRequest 对象的 startAsync() 方法开始,最终到异步状态机 AsyncStateMachine 对象的 asyncStart() 方法。

  • 开启异步并不会触发异步 listener 的 start 事件,因为开启异步构造的上下文对象并没有设置 listener(可能 tomcat 异步实现者并没有考虑这个问题)。

  • 异步调用的所有状态由 AsyncStateMachine 对象来保持维护,该类属于Http11Processor 对象,每个Http11Processor 对像关联处理一个底层 socket,通过这种方式来关联异步状态机和请求。

  • AsyncStateMachine 对象中异步的初始状态为 AsyncState.DISPATCHED,通过开启异步改变其状态为 AsyncState.STARTING。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yzgu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值