Tomcat 处理 http 请求之源码分析 | 京东云技术团队
字数 1533 2025-08-10 22:08:13

Tomcat HTTP请求处理源码分析教学文档

1. 概述

本文详细分析Tomcat处理HTTP请求的完整流程,从请求获取到最终Servlet处理的全过程。主要分为三个核心部分:

  1. 请求获取与包装处理
  2. 请求传递给Container
  3. Container处理请求流程

2. 请求获取与包装处理

2.1 连接接收

Tomcat通过Connector组件监听端口,以JIoEndpoint为例:

protected class Acceptor extends AbstractEndpoint.Acceptor {
    @Override
    public void run() {
        while (running) {
            try {
                // 当前连接数控制
                countUpOrAwaitConnection();
                Socket socket = null;
                try {
                    // 取出队列中的连接请求
                    socket = serverSocketFactory.acceptSocket(serverSocket);
                } catch (IOException ioe) {
                    countDownConnection();
                }
                
                if (running && !paused && setSocketOptions(socket)) {
                    // 处理请求
                    if (!processSocket(socket)) {
                        countDownConnection();
                        closeSocket(socket);
                    }
                } else {
                    countDownConnection();
                    closeSocket(socket);
                }
            }
        }
    }
}

2.2 请求处理

processSocket()方法对socket进行包装并交给线程池处理:

protected boolean processSocket(Socket socket) {
    try {
        SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket);
        wrapper.setKeepAliveLeft(getMaxKeepAliveRequests());
        wrapper.setSecure(isSSLEnabled());
        // 交给线程池处理连接
        getExecutor().execute(new SocketProcessor(wrapper));
        return true;
    }
}

2.3 SocketProcessor处理

线程池任务SocketProcessor将Socket交给handler处理:

protected class SocketProcessor implements Runnable {
    protected SocketWrapper<Socket> socket = null;
    protected SocketStatus status = null;
    
    @Override
    public void run() {
        boolean launch = false;
        synchronized (socket) {
            SocketState state = SocketState.OPEN;
            try {
                serverSocketFactory.handshake(socket.getSocket());
                if ((state != SocketState.CLOSED)) {
                    // 委派给Handler来处理
                    if (status == null) {
                        state = handler.process(socket, SocketStatus.OPEN_READ);
                    } else {
                        state = handler.process(socket, status);
                    }
                }
            }
        }
    }
}

2.4 Http11Processor处理

Http11ConnectionHandler创建Http11Processor处理器:

public SocketState process(SocketWrapper socketWrapper) {
    RequestInfo rp = request.getRequestProcessor();
    rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
    
    // 设置I/O
    setSocketWrapper(socketWrapper);
    getInputBuffer().init(socketWrapper, endpoint);
    getOutputBuffer().init(socketWrapper, endpoint);
    
    while (!getErrorState().isError() && keepAlive && !comet && !isAsync() 
           && upgradeInbound == null && httpUpgradeHandler == null 
           && !endpoint.isPaused()) {
        if (!getErrorState().isError()) {
            // 设置过滤器并解析请求头
            rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
            try {
                // 请求预处理
                prepareRequest();
                if (!getErrorState().isError()) {
                    try {
                        rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
                        // 交由适配器处理
                        adapter.service(request, response);
                        if(keepAlive && !getErrorState().isError() 
                           && (response.getErrorException() != null 
                               || (!isAsync() && statusDropsConnection(response.getStatus())))) {
                            setErrorState(ErrorState.CLOSE_CLEAN, null);
                        }
                    }
                }
            }
        }
    }
    setCometTimeouts(socketWrapper);
}

3. 请求传递给Container

3.1 CoyoteAdapter处理

CoyoteAdapter的service方法主要完成两个任务:

  1. org.apache.coyote.Request/Response到HttpServletRequest/Response的转换
  2. Context和Wrapper定位
public void service(org.apache.coyote.Request req, org.apache.coyote.Response res) {
    postParseSuccess = postParseRequest(req, request, res, response);
    connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
}

3.2 请求映射

在postParseRequest方法中进行URI到Context/Wrapper的映射:

connector.getMapper().map(serverName, decodedURI, version, request.getMappingData());
request.setContext((Context) request.getMappingData().context);
request.setWrapper((Wrapper) request.getMappingData().wrapper);

3.3 Mapper初始化

Mapper保存所有容器信息,初始化过程:

public void startInternal() throws LifecycleException {
    setState(LifecycleState.STARTING);
    findDefaultHost();
    Engine engine = (Engine) connector.getService().getContainer();
    addListeners(engine);
    Container[] conHosts = engine.findChildren();
    for (Container conHost : conHosts) {
        Host host = (Host) conHost;
        if (!LifecycleState.NEW.equals(host.getState())) {
            registerHost(host);
        }
    }
}

MapperListener作为监听器,当容器变化时更新Mapper中的信息。

4. Container处理请求流程

4.1 处理链

Container处理请求的调用链时序图如下:

  1. CoyoteAdapter.service()
  2. StandardEngineValve.invoke()
  3. StandardHostValve.invoke()
  4. StandardContextValve.invoke()
  5. StandardWrapperValve.invoke()

4.2 StandardWrapperValve处理

最终StandardWrapperValve将请求交给Servlet处理:

// 伪代码表示处理流程
StandardWrapperValve.invoke() {
    // 分配过滤器链
    ApplicationFilterChain filterChain = createFilterChain();
    // 调用过滤器链
    filterChain.doFilter(request.getRequest(), response.getResponse());
    // 最终调用Servlet.service()
}

5. 关键点总结

  1. 连接接收:通过Acceptor线程接收连接,使用计数器控制并发连接数
  2. 请求处理:SocketProcessor线程处理请求,使用Http11Processor解析HTTP协议
  3. 请求转换:CoyoteAdapter将coyote.Request/Response转换为servlet.Request/Response
  4. 请求映射:通过Mapper实现URI到Context/Wrapper的映射
  5. 容器处理:通过Valve链式调用,最终由StandardWrapperValve交给Servlet处理
  6. 监听机制:MapperListener监听容器变化,保持Mapper信息同步更新

6. 性能考虑

  1. 连接数控制:countUpOrAwaitConnection/countDownConnection机制
  2. 线程池处理:Executor处理SocketProcessor任务
  3. Keep-Alive处理:wrapper.setKeepAliveLeft()管理长连接请求数
  4. 异步处理:支持异步和Comet模式

7. 扩展点

  1. ProtocolHandler:可替换不同的协议处理器
  2. Mapper:自定义URI映射逻辑
  3. Valve:可在处理链中插入自定义Valve
  4. Filter:通过FilterChain实现请求预处理和后处理

通过深入理解Tomcat处理HTTP请求的完整流程,可以更好地进行性能调优和功能扩展。

Tomcat HTTP请求处理源码分析教学文档 1. 概述 本文详细分析Tomcat处理HTTP请求的完整流程,从请求获取到最终Servlet处理的全过程。主要分为三个核心部分: 请求获取与包装处理 请求传递给Container Container处理请求流程 2. 请求获取与包装处理 2.1 连接接收 Tomcat通过Connector组件监听端口,以JIoEndpoint为例: 2.2 请求处理 processSocket() 方法对socket进行包装并交给线程池处理: 2.3 SocketProcessor处理 线程池任务SocketProcessor将Socket交给handler处理: 2.4 Http11Processor处理 Http11ConnectionHandler创建Http11Processor处理器: 3. 请求传递给Container 3.1 CoyoteAdapter处理 CoyoteAdapter的service方法主要完成两个任务: org.apache.coyote.Request/Response到HttpServletRequest/Response的转换 Context和Wrapper定位 3.2 请求映射 在postParseRequest方法中进行URI到Context/Wrapper的映射: 3.3 Mapper初始化 Mapper保存所有容器信息,初始化过程: MapperListener作为监听器,当容器变化时更新Mapper中的信息。 4. Container处理请求流程 4.1 处理链 Container处理请求的调用链时序图如下: CoyoteAdapter.service() StandardEngineValve.invoke() StandardHostValve.invoke() StandardContextValve.invoke() StandardWrapperValve.invoke() 4.2 StandardWrapperValve处理 最终StandardWrapperValve将请求交给Servlet处理: 5. 关键点总结 连接接收 :通过Acceptor线程接收连接,使用计数器控制并发连接数 请求处理 :SocketProcessor线程处理请求,使用Http11Processor解析HTTP协议 请求转换 :CoyoteAdapter将coyote.Request/Response转换为servlet.Request/Response 请求映射 :通过Mapper实现URI到Context/Wrapper的映射 容器处理 :通过Valve链式调用,最终由StandardWrapperValve交给Servlet处理 监听机制 :MapperListener监听容器变化,保持Mapper信息同步更新 6. 性能考虑 连接数控制:countUpOrAwaitConnection/countDownConnection机制 线程池处理:Executor处理SocketProcessor任务 Keep-Alive处理:wrapper.setKeepAliveLeft()管理长连接请求数 异步处理:支持异步和Comet模式 7. 扩展点 ProtocolHandler :可替换不同的协议处理器 Mapper :自定义URI映射逻辑 Valve :可在处理链中插入自定义Valve Filter :通过FilterChain实现请求预处理和后处理 通过深入理解Tomcat处理HTTP请求的完整流程,可以更好地进行性能调优和功能扩展。