Tomcat 处理 http 请求之源码分析 | 京东云技术团队
字数 1533 2025-08-10 22:08:13
Tomcat HTTP请求处理源码分析教学文档
1. 概述
本文详细分析Tomcat处理HTTP请求的完整流程,从请求获取到最终Servlet处理的全过程。主要分为三个核心部分:
- 请求获取与包装处理
- 请求传递给Container
- 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方法主要完成两个任务:
- org.apache.coyote.Request/Response到HttpServletRequest/Response的转换
- 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处理请求的调用链时序图如下:
- CoyoteAdapter.service()
- StandardEngineValve.invoke()
- StandardHostValve.invoke()
- StandardContextValve.invoke()
- StandardWrapperValve.invoke()
4.2 StandardWrapperValve处理
最终StandardWrapperValve将请求交给Servlet处理:
// 伪代码表示处理流程
StandardWrapperValve.invoke() {
// 分配过滤器链
ApplicationFilterChain filterChain = createFilterChain();
// 调用过滤器链
filterChain.doFilter(request.getRequest(), response.getResponse());
// 最终调用Servlet.service()
}
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请求的完整流程,可以更好地进行性能调优和功能扩展。