Tomcat异步分析

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));

启动分析

Tomcat异步分析_第1张图片
image.png

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;
        }

任务提交后的后续处理

Tomcat异步分析_第2张图片
image.png

从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

你可能感兴趣的:(Tomcat异步分析)