Tomcat -- 请求处理流程

在这里插入图片描述

请求流程

Mapper组件
  • mapper组件将用户请求URL定位到具体的Servlet
工作原理(同SpringMVC)
  • mapper组件中保存了Web应用的配置信息,即容器组件与访问路径的映射关系
  • 映射关系,如多层次的Map:
    ○ Host容器中配置域名
    ○ Context容器的web应用路径
    ○ Wrapper容器里的Servlet映射的路径
  • 当一个请求进来时
    ○ Mapper组件会解析请求的URL的域名和路径
    ○ 到自己的映射关系Map中查找Wrapper,定位到唯一的Servlet
具体流程

在这里插入图片描述

请求连接和协议解析
  • Connector组件的Endpoint中的Acceptor监听客户端套接字连接并接收Socket
  • 将连接交给线程池Exectuor处理,开始执行请求响应任务
  • Processor组件读取到消息报文,解析请求行、请求头、请求体,封装成Request对象
请求路由和处理
  • Mapper组件根据请求行的URL值和请求头的Host值匹配由那个host、context、wrapper容器进行处理
  • CoyoteAdaptor组件负责将Connector组件和Engine容器适配关联,把生成的Request对象和响应的Response对象传递给Engine容器,并调用Pipeline
  • Engine容器的管道开始处理,管道中包含若干个Valve,每个Valve负责部分处理逻辑,执行完Valve后会执行基础的Valve – StandardEngineValve,负责调用Host容器的Pipeline
  • Host容器的管道开始同上流程处理,最后执行Content容器的Pipeline
  • Content容器的管道开始同上流程处理,最后执行Wrapper容器的Pipeline
  • Wrapper容器的管道开始同上流程处理
  • 最后执行Wrapper容器对应的Servlet对象的处理方法

源码跟踪

请求流程图
在这里插入图片描述
请求时序图
在这里插入图片描述

源码入口
  • org.apache.tomcat.util.net.NioEndpoint#startInternal (启动完成,接收请求)
  • org.apache.tomcat.util.net.NioEndpoint.Poller#run (处理接收的请求)
  • org.apache.tomcat.util.net.NioEndpoint.Poller#processKey
  • org.apache.tomcat.util.net.AbstractEndpoint#processSocket
执行AbstractEndpoint.processSocket
  • org.apache.tomcat.util.net.AbstractEndpoint#processSocket
  • 由Executor线程池执行业务SocketWrapperBase.run
  • Connector组件的Endpoint中的Acceptor监听客户端套接字连接并接收Socket
public boolean processSocket(SocketWrapperBase<S> socketWrapper,
                             SocketEvent event, boolean dispatch) {
    Executor executor = getExecutor();
    if (dispatch && executor != null) {
        executor.execute(sc);
    } else {
        sc.run();
    }

}
执行SocketWrapperBase.run
  • org.apache.tomcat.util.net.SocketProcessorBase#run
  • 调用doRun方法
    ○ 执行3次握手
    ○ 获取handler并进行请求处理
  • 将连接交给线程池Exectuor处理,开始执行请求响应任务
public final void run() {
    synchronized (socketWrapper) {
        doRun();
    }
}

protected void doRun() {
    Poller poller = NioEndpoint.this.poller;
    if (poller == null) {
        socketWrapper.close();
        return;
    }
    //执行3次握手
    int handshake = -1;
    //....
    if (handshake == 0) {
        SocketState state = SocketState.OPEN;
        if (event == null) {
            state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);
        } else {
            //获取handler并进行请求处理
            state = getHandler().process(socketWrapper, event);
        }
        if (state == SocketState.CLOSED) {
            poller.cancelledKey(getSelectionKey(), socketWrapper);
        }
    } 
    //....
}
执行AbstractProtocol.process
  • 获取当前Processor
  • 调用processor的process方法(在此Endpoint将请求的信息交给Processor)
  • Processor组件读取到消息报文,解析请求行、请求头、请求体,封装成Request对象
public SocketState process(SocketWrapperBase<S> wrapper, SocketEvent status) {

    S socket = wrapper.getSocket();
    //拿到当前Processor
    Processor processor = (Processor) wrapper.getCurrentProcessor();
    //....
    SocketState state = SocketState.CLOSED;
    //调用processor的process方法
    state = processor.process(wrapper, status);
    //...
}
执行AbstractProcessorLight.process
  • 执行dispatch或执行service方法
public SocketState process(SocketWrapperBase<?> socketWrapper, SocketEvent status) throws IOException {

    SocketState state = SocketState.CLOSED;
    Iterator<DispatchType> dispatches = null;
    do {
        if (dispatches != null) {
            DispatchType nextDispatch = dispatches.next();
            state = dispatch(nextDispatch.getSocketStatus());
            if (!dispatches.hasNext()) {
                state = checkForPipelinedData(state, socketWrapper);
            }
        } else if (status == SocketEvent.DISCONNECT) {
            // Do nothing here, just wait for it to get recycled
        } else if (isAsync() || isUpgrade() || state == SocketState.ASYNC_END) {
            //执行dispatch
            state = dispatch(status);
            state = checkForPipelinedData(state, socketWrapper);
        } else if (status == SocketEvent.OPEN_WRITE) {
            state = SocketState.LONG;
        } else if (status == SocketEvent.OPEN_READ) {
            //执行service方法
            state = service(socketWrapper);
        }
        //....
    } while (state == SocketState.ASYNC_END ||
             dispatches != null && state != SocketState.CLOSED);

    return state;
}

执行Http11Processor.service
  • org.apache.coyote.http11.Http11Processor#service
  • 解析请求行、请求头、请求体,封装成Request对象
  • 获取adapter(CoyoteAdaptor),调用service方法
  • CoyoteAdaptor组件负责将Connector组件和Engine容器适配关联
public SocketState service(SocketWrapperBase<?> socketWrapper)  throws IOException {
	//获取adapter(CoyoteAdaptor),调用service方法
    getAdapter().service(request, response);
}
执行CoyoteAdaptor.service
  • 获取到Request和Response对象
  • 调用容器,把生成的Request对象和响应的Response对象传递给Engine容器
public void service(org.apache.coyote.Request req, org.apache.coyote.Response res)
    throws Exception {
    //获取到Request和Response对象
    Request request = (Request) req.getNote(ADAPTER_NOTES);
    Response response = (Response) res.getNote(ADAPTER_NOTES);
    postParseSuccess = postParseRequest(req, request, res, response);
    //调用容器,获取Engin管道阀Valve
    connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
    //。。。。
}

执行责任链xxxValve.invoke
  • 执行StandardServiceValve.invoke
    a. 获取Host,调用Host容器的Pipeline
    b. Engine容器的管道开始处理,管道中包含若干个Valve,每个Valve负责部分处理逻辑,执行完Valve后会执行基础的Valve
  • 执行StandardHostValve.invoke
    a. 获取Context,调用Context容器的Pipeline
  • 执行StandardContextValve.invoke
    a. 获取Wrapper,调用Wrapper容器的Pipeline
获取Servlet – Wrapper.invoke
  • 从Container中获取Wrapper
  • 从Wrapper中获取到Servlet,至此拿到的就是具体业务Servlet
  • 将Servlet封装到构造的FilterChain过滤器链中
  • 执行过滤器链中的filter,并传入ServletRequest和ServletResponse
public final void invoke(Request request, Response response) throws IOException, ServletException {
    //从Container中获取Wrapper
    StandardWrapper wrapper = (StandardWrapper) getContainer();
    Servlet servlet = null;
    Context context = (Context) wrapper.getParent();
    //获取到servlet
    servlet = wrapper.allocate();

    //将Servlet封装到FilterChain过滤器链中
    ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
	//。。。。
    //执行过滤器链中的filter
    filterChain.doFilter(request.getRequest(),response.getResponse());

}
执行过滤器链中的filter
  • 获取到ServletRequest、ServletResponse执行过滤器
  • 调用servlet.service方法
  • 调用HttpServlet.service
    ○ 执行doGet、doPost方法
public void doFilter(ServletRequest request, ServletResponse response){
    internalDoFilter(request,response);
}

private void internalDoFilter(ServletRequest request,
                              ServletResponse response){
	//....
    //执行过滤器
    //调用Servlet.service方法
    servlet.service(request, response);
}
执行HttpServlet.service
  • 获取请求方式
  • 执行对应的请求方法,如:doPost、doGet等
protected void service(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {
    //获取请求方式
    String method = req.getMethod();
    //执行对应的请求方法
    if (method.equals(METHOD_GET)) {
        doGet(req, resp);
    } else if (method.equals(METHOD_HEAD)) {
        doHead(req, resp);
    } else if (method.equals(METHOD_POST)) {
        doPost(req, resp);

    } else if (method.equals(METHOD_PUT)) {
        doPut(req, resp);

    } else if (method.equals(METHOD_DELETE)) {
        doDelete(req, resp);

    } else if (method.equals(METHOD_OPTIONS)) {
        doOptions(req,resp);

    } else if (method.equals(METHOD_TRACE)) {
        doTrace(req,resp);
    } 
}

Http长连接的支持

  • 客户端请求会携带Connection: keep-alive
  • service方法会解析,并使用keepAlive参数记录是否满足长连接条件
  • 不满足长连接条件则返回的响应头携带Connection: close,表示关闭连接
  • 满足长连接条件则不返回Connection参数
org.apache.coyote.http11.Http11Processor#service

public SocketState service(SocketWrapperBase<?> socketWrapper)
    throws IOException {
    RequestInfo rp = request.getRequestProcessor();
    rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);

    // Setting up the I/O
    setSocketWrapper(socketWrapper);

    // Flags
    keepAlive = true;
    openSocket = false;
    readComplete = true;
    boolean keptAlive = false;
    SendfileState sendfileState = SendfileState.DONE;

    //todo 控制tomcat长连接原理 while循环  keepAlive
    while (!getErrorState().isError() && keepAlive && !isAsync() && upgradeToken == null &&
           sendfileState == SendfileState.DONE && !protocol.isPaused()) {

        // Parsing the request header
        try {
            if (!inputBuffer.parseRequestLine(keptAlive, protocol.getConnectionTimeout(),
                                              protocol.getKeepAliveTimeout())) {
                if (inputBuffer.getParsingRequestLinePhase() == -1) {
                    return SocketState.UPGRADING;
                } else if (handleIncompleteRequestLineRead()) {
                    break;
                }
            }

            if (protocol.isPaused()) {
                // 503 - Service unavailable
                response.setStatus(503);
                setErrorState(ErrorState.CLOSE_CLEAN, null);
            } else {
                keptAlive = true;
                // Set this every time in case limit has been changed via JMX
                request.getMimeHeaders().setLimit(protocol.getMaxHeaderCount());
                if (!inputBuffer.parseHeaders()) {
                    // We've read part of the request, don't recycle it
                    // instead associate it with the socket
                    openSocket = true;
                    readComplete = false;
                    break;
                }
                if (!protocol.getDisableUploadTimeout()) {
                    socketWrapper.setReadTimeout(protocol.getConnectionUploadTimeout());
                }
            }
        } catch (IOException e) {
            if (log.isDebugEnabled()) {
                log.debug(sm.getString("http11processor.header.parse"), e);
            }
            setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e);
            break;
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            UserDataHelper.Mode logMode = userDataHelper.getNextMode();
            if (logMode != null) {
                String message = sm.getString("http11processor.header.parse");
                switch (logMode) {
                    case INFO_THEN_DEBUG:
                        message += sm.getString("http11processor.fallToDebug");
                        //$FALL-THROUGH$
                    case INFO:
                        log.info(message, t);
                        break;
                    case DEBUG:
                        log.debug(message, t);
                }
            }
            // 400 - Bad Request
            response.setStatus(400);
            setErrorState(ErrorState.CLOSE_CLEAN, t);
        }

        // Has an upgrade been requested?
        Enumeration<String> connectionValues = request.getMimeHeaders().values("Connection");
        boolean foundUpgrade = false;
        while (connectionValues.hasMoreElements() && !foundUpgrade) {
            String connectionValue = connectionValues.nextElement();
            if (connectionValue != null) {
                foundUpgrade = connectionValue.toLowerCase(Locale.ENGLISH).contains("upgrade");
            }
        }

        if (foundUpgrade) {
            // Check the protocol
            String requestedProtocol = request.getHeader("Upgrade");

            UpgradeProtocol upgradeProtocol = protocol.getUpgradeProtocol(requestedProtocol);
            if (upgradeProtocol != null) {
                if (upgradeProtocol.accept(request)) {
                    response.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS);
                    response.setHeader("Connection", "Upgrade");
                    response.setHeader("Upgrade", requestedProtocol);
                    action(ActionCode.CLOSE,  null);
                    getAdapter().log(request, response, 0);

                    InternalHttpUpgradeHandler upgradeHandler =
                        upgradeProtocol.getInternalUpgradeHandler(
                        socketWrapper, getAdapter(), cloneRequest(request));
                    UpgradeToken upgradeToken = new UpgradeToken(upgradeHandler, null, null);
                    action(ActionCode.UPGRADE, upgradeToken);
                    return SocketState.UPGRADING;
                }
            }
        }

        if (getErrorState().isIoAllowed()) {
            // Setting up filters, and parse some request headers
            rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
            try {
                prepareRequest();
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString("http11processor.request.prepare"), t);
                }
                // 500 - Internal Server Error
                response.setStatus(500);
                setErrorState(ErrorState.CLOSE_CLEAN, t);
            }
        }
        //最大活跃的http请求数量
        int maxKeepAliveRequests = protocol.getMaxKeepAliveRequests();
        if (maxKeepAliveRequests == 1) {
            keepAlive = false;
        } else if (maxKeepAliveRequests > 0 &&
                   socketWrapper.decrementKeepAlive() <= 0) {
            keepAlive = false;
        }

        // Process the request in the adapter
        if (getErrorState().isIoAllowed()) {
            try {
                rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
                getAdapter().service(request, response);
                // Handle when the response was committed before a serious
                // error occurred.  Throwing a ServletException should both
                // set the status to 500 and set the errorException.
                // If we fail here, then the response is likely already
                // committed, so we can't try and set headers.
                if(keepAlive && !getErrorState().isError() && !isAsync() &&
                   statusDropsConnection(response.getStatus())) {
                    setErrorState(ErrorState.CLOSE_CLEAN, null);
                }
            } catch (InterruptedIOException e) {
                setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e);
            } catch (HeadersTooLargeException e) {
                log.error(sm.getString("http11processor.request.process"), e);
                // The response should not have been committed but check it
                // anyway to be safe
                if (response.isCommitted()) {
                    setErrorState(ErrorState.CLOSE_NOW, e);
                } else {
                    response.reset();
                    response.setStatus(500);
                    setErrorState(ErrorState.CLOSE_CLEAN, e);
                    response.setHeader("Connection", "close"); // TODO: Remove
                }
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                log.error(sm.getString("http11processor.request.process"), t);
                // 500 - Internal Server Error
                response.setStatus(500);
                setErrorState(ErrorState.CLOSE_CLEAN, t);
                getAdapter().log(request, response, 0);
            }
        }

        // Finish the handling of the request
        rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
        if (!isAsync()) {
            // If this is an async request then the request ends when it has
            // been completed. The AsyncContext is responsible for calling
            // endRequest() in that case.
            endRequest();
        }
        rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);

        // If there was an error, make sure the request is counted as
        // and error, and update the statistics counter
        if (getErrorState().isError()) {
            response.setStatus(500);
        }

        if (!isAsync() || getErrorState().isError()) {
            request.updateCounters();
            if (getErrorState().isIoAllowed()) {
                inputBuffer.nextRequest();
                outputBuffer.nextRequest();
            }
        }

        if (!protocol.getDisableUploadTimeout()) {
            int connectionTimeout = protocol.getConnectionTimeout();
            if(connectionTimeout > 0) {
                socketWrapper.setReadTimeout(connectionTimeout);
            } else {
                socketWrapper.setReadTimeout(0);
            }
        }

        rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);

        sendfileState = processSendfile(socketWrapper);
    }

    rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);

    if (getErrorState().isError() || protocol.isPaused()) {
        return SocketState.CLOSED;
    } else if (isAsync()) {
        return SocketState.LONG;
    } else if (isUpgrade()) {
        return SocketState.UPGRADING;
    } else {
        if (sendfileState == SendfileState.PENDING) {
            return SocketState.SENDFILE;
        } else {
            if (openSocket) {
                if (readComplete) {
                    return SocketState.OPEN;
                } else {
                    return SocketState.LONG;
                }
            } else {
                return SocketState.CLOSED;
            }
        }
    }
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值