第三章-Tomcat请求处理原理 - 指南
⚙️ 第三章:Tomcat 请求处理原理
目录
3.1 请求到达与解析
3.1.1 请求到达流程
整体流程图
详细步骤说明
1. 网络层接收
// NIO 连接器接收请求
public class Http11NioProtocol extends AbstractHttp11Protocol<NioChannel> {
@Override
protected AbstractEndpoint.Handler<NioChannel> getHandler() {
return new Http11ConnectionHandler(this);
}
}
2. 协议解析
// HTTP 协议解析器
public class Http11Processor extends AbstractProcessorLight {
@Override
public SocketState service(SocketWrapperBase<?> socketWrapper)
throws IOException {
// 1. 解析请求行
if (!inputBuffer.parseRequestLine(keptAlive)) {
if (inputBuffer.getParsingRequestLinePhase() == -1) {
return SocketState.UPGRADING;
} else if (handleIncompleteRequestLineRead()) {
break;
}
}
// 2. 解析请求头
if (!inputBuffer.parseHeaders()) {
if (inputBuffer.getParsingRequestLinePhase() == -1) {
return SocketState.UPGRADING;
} else if (handleIncompleteRequestLineRead()) {
break;
}
}
// 3. 处理请求
return process(socketWrapper);
}
}
3. CoyoteAdapter 适配
// CoyoteAdapter 适配器
public class CoyoteAdapter implements Adapter {
@Override
public void service(org.apache.coyote.Request req,
org.apache.coyote.Response res)
throws Exception {
// 1. 创建 Request 和 Response 对象
Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);
if (request == null) {
request = connector.createRequest();
request.setCoyoteRequest(req);
response = connector.createResponse();
response.setCoyoteResponse(res);
}
// 2. 设置请求属性
request.setCoyoteRequest(req);
response.setCoyoteResponse(res);
// 3. 调用容器的 Pipeline
connector.getService().getContainer().getPipeline()
.getFirst().invoke(request, response);
}
}
3.1.2 请求解析详解
HTTP 请求解析
// 请求行解析
public class Http11InputBuffer {
public boolean parseRequestLine(boolean keptAlive) throws IOException {
// 解析方法
if (parsingRequestLinePhase == 0) {
if (parsingRequestLineStart == -1) {
parsingRequestLineStart = 0;
}
byte chr = 0;
do {
int pos = parsingRequestLineStart;
byte[] buf = bufferedReadBuffer;
int end = lastValid;
while (pos < end) {
chr = buf[pos];
if (chr == Constants.SP || chr == Constants.HTAB) {
break;
}
pos++;
}
if (pos == end) {
if (keptAlive) {
return false;
}
throw new IOException("Request line too long");
}
parsingRequestLineStart = pos;
parsingRequestLinePhase = 1;
} while (chr == Constants.SP || chr == Constants.HTAB);
}
// 解析 URI
if (parsingRequestLinePhase == 1) {
return parseRequestLineURI();
}
// 解析协议版本
if (parsingRequestLinePhase == 2) {
return parseRequestLineProtocol();
}
return true;
}
}
请求头解析
// 请求头解析
public boolean parseHeaders() throws IOException {
if (parsingHeader) {
return true;
}
parsingHeader = true;
while (true) {
// 读取一行
if (!fill()) {
return false;
}
// 检查是否为空行(请求头结束)
if (buf[pos] == Constants.CR || buf[pos] == Constants.LF) {
parsingHeader = false;
return true;
}
// 解析单个请求头
if (!parseHeader()) {
return false;
}
}
}
3.2 请求分发机制
3.2.1 路由层次结构
路由流程图
详细路由步骤
1. Engine 路由到 Host
// StandardEngine 路由逻辑
public class StandardEngine extends ContainerBase implements Engine {
@Override
public void invoke(Request request, Response response)
throws IOException, ServletException {
// 1. 获取请求的 Host 头
String hostname = request.getServerName();
if (hostname == null) {
hostname = getDefaultHost();
}
// 2. 查找对应的 Host
Host host = findChild(hostname);
if (host == null) {
host = findChild(getDefaultHost());
}
// 3. 调用 Host 的 invoke 方法
if (host != null) {
host.invoke(request, response);
} else {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
}
}
}
2. Host 路由到 Context
// StandardHost 路由逻辑
public class StandardHost extends ContainerBase implements Host {
@Override
public void invoke(Request request, Response response)
throws IOException, ServletException {
// 1. 获取请求路径
String requestPath = request.getRequestPath();
// 2. 查找匹配的 Context
Context context = findContext(requestPath);
if (context == null) {
context = findContext("");
}
// 3. 调用 Context 的 invoke 方法
if (context != null) {
context.invoke(request, response);
} else {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
private Context findContext(String path) {
// 1. 精确匹配
Context context = contexts.get(path);
if (context != null) {
return context;
}
// 2. 最长前缀匹配
String longestMatch = "";
Context longestContext = null;
for (Map.Entry<String, Context> entry : contexts.entrySet()) {
String contextPath = entry.getKey();
if (path.startsWith(contextPath) &&
contextPath.length() > longestMatch.length()) {
longestMatch = contextPath;
longestContext = entry.getValue();
}
}
return longestContext;
}
}
3. Context 路由到 Wrapper
// StandardContext 路由逻辑
public class StandardContext extends ContainerBase implements Context {
@Override
public void invoke(Request request, Response response)
throws IOException, ServletException {
// 1. 获取 Servlet 路径
String servletPath = request.getServletPath();
// 2. 查找匹配的 Wrapper
Wrapper wrapper = findWrapper(servletPath);
if (wrapper == null) {
wrapper = findWrapper("");
}
// 3. 调用 Wrapper 的 invoke 方法
if (wrapper != null) {
wrapper.invoke(request, response);
} else {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
private Wrapper findWrapper(String path) {
// 1. 精确匹配
Wrapper wrapper = wrappers.get(path);
if (wrapper != null) {
return wrapper;
}
// 2. 模式匹配
for (Map.Entry<String, Wrapper> entry : wrappers.entrySet()) {
String pattern = entry.getKey();
if (matchPattern(path, pattern)) {
return entry.getValue();
}
}
return null;
}
}
4. Wrapper 调用 Servlet
// StandardWrapper 调用逻辑
public class StandardWrapper extends ContainerBase implements Wrapper {
@Override
public void invoke(Request request, Response response)
throws IOException, ServletException {
// 1. 获取 Servlet 实例
Servlet servlet = allocate();
// 2. 调用 Servlet 的 service 方法
try {
servlet.service(request, response);
} finally {
// 3. 释放 Servlet 实例
deallocate(servlet);
}
}
private Servlet allocate() throws ServletException {
// 1. 检查是否已加载
if (instance == null) {
load();
}
// 2. 返回 Servlet 实例
return instance;
}
}
3.2.2 路由配置示例
Host 配置
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!-- 应用上下文 -->
<Context path="/myapp" docBase="myapp" />
<Context path="/api" docBase="api" />
<!-- 默认应用 -->
<Context path="" docBase="ROOT" />
</Host>
Context 配置
<Context path="/myapp" docBase="myapp">
<!-- Servlet 映射 -->
<Servlet name="MyServlet" class="com.example.MyServlet" />
<ServletMapping name="MyServlet" urlPattern="/myservlet" />
<!-- 过滤器 -->
<Filter name="MyFilter" class="com.example.MyFilter" />
<FilterMapping name="MyFilter" urlPattern="/*" />
</Context>
3.3 NIO 事件循环模型
3.3.1 NIO 模型概述
事件循环架构
核心组件
1. Acceptor 线程
// Acceptor 线程
public class Acceptor<U> extends AbstractEndpoint.Acceptor<U> {
@Override
public void run() {
while (endpoint.isRunning()) {
try {
// 1. 接受连接
SocketChannel socket = serverSock.accept();
// 2. 设置非阻塞模式
socket.configureBlocking(false);
// 3. 注册到 Poller
getPoller0().register(socket);
} catch (Exception e) {
// 处理异常
}
}
}
}
2. Poller 线程
// Poller 线程
public class Poller implements Runnable {
@Override
public void run() {
while (true) {
try {
// 1. 等待事件
int keyCount = selector.select(selectorTimeout);
// 2. 处理就绪的通道
if (keyCount > 0) {
Iterator<SelectionKey> iterator =
selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
// 3. 处理 I/O 事件
processKey(key);
}
}
} catch (Exception e) {
// 处理异常
}
}
}
private void processKey(SelectionKey key) {
if (key.isReadable()) {
// 处理读事件
processRead(key);
} else if (key.isWritable()) {
// 处理写事件
processWrite(key);
}
}
}
3. Worker 线程池
// Worker 线程池
public class Executor implements java.util.concurrent.Executor {
private final ThreadPoolExecutor executor;
@Override
public void execute(Runnable command) {
// 1. 检查线程池状态
if (executor.isShutdown()) {
return;
}
// 2. 提交任务到线程池
executor.execute(command);
}
private void processRequest(SocketChannel channel) {
// 1. 创建请求处理任务
Runnable task = new RequestProcessor(channel);
// 2. 提交到线程池
executor.execute(task);
}
}
3.3.2 事件处理流程
详细处理步骤
// 请求处理流程
public class Http11NioProcessor extends AbstractProcessorLight {
@Override
public SocketState service(SocketWrapperBase<NioChannel> socketWrapper)
throws IOException {
// 1. 读取请求数据
if (!inputBuffer.parseRequestLine(keptAlive)) {
return SocketState.UPGRADING;
}
// 2. 解析请求头
if (!inputBuffer.parseHeaders()) {
return SocketState.UPGRADING;
}
// 3. 处理请求
return process(socketWrapper);
}
private SocketState process(SocketWrapperBase<NioChannel> socketWrapper)
throws IOException {
// 1. 创建请求和响应对象
Request request = new Request();
Response response = new Response();
// 2. 设置请求属性
request.setCoyoteRequest(coyoteRequest);
response.setCoyoteResponse(coyoteResponse);
// 3. 调用适配器
adapter.service(request, response);
// 4. 处理响应
return processResponse(request, response);
}
}
3.4 请求处理详细流程
3.4.1 完整处理流程
流程图
详细代码实现
1. 请求接收
// 连接器接收请求
public class Http11NioProtocol extends AbstractHttp11Protocol<NioChannel> {
@Override
protected AbstractEndpoint.Handler<NioChannel> getHandler() {
return new Http11ConnectionHandler(this);
}
}
// 连接处理器
public class Http11ConnectionHandler extends AbstractConnectionHandler<NioChannel,Http11NioProcessor> {
@Override
protected Http11NioProcessor createProcessor() {
Http11NioProcessor processor = new Http11NioProcessor(this);
processor.setAdapter(getAdapter());
return processor;
}
}
2. 请求解析
// 请求解析器
public class Http11InputBuffer {
public boolean parseRequestLine(boolean keptAlive) throws IOException {
// 解析请求行:方法 URI 协议版本
// GET /myapp/servlet HTTP/1.1
return parseRequestLineInternal(keptAlive);
}
public boolean parseHeaders() throws IOException {
// 解析请求头
// Host: localhost:8080
// Content-Type: application/json
// Content-Length: 100
return parseHeadersInternal();
}
}
3. 请求路由
// 请求路由
public class CoyoteAdapter implements Adapter {
@Override
public void service(org.apache.coyote.Request req,
org.apache.coyote.Response res)
throws Exception {
// 1. 创建 Request 和 Response 对象
Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);
if (request == null) {
request = connector.createRequest();
request.setCoyoteRequest(req);
response = connector.createResponse();
response.setCoyoteResponse(res);
}
// 2. 设置请求属性
request.setCoyoteRequest(req);
response.setCoyoteResponse(res);
// 3. 调用容器的 Pipeline
connector.getService().getContainer().getPipeline()
.getFirst().invoke(request, response);
}
}
4. Servlet 调用
// Servlet 调用
public class StandardWrapper extends ContainerBase implements Wrapper {
@Override
public void invoke(Request request, Response response)
throws IOException, ServletException {
// 1. 获取 Servlet 实例
Servlet servlet = allocate();
// 2. 调用 Servlet 的 service 方法
try {
servlet.service(request, response);
} finally {
// 3. 释放 Servlet 实例
deallocate(servlet);
}
}
}
3.5 响应生成与返回
3.5.1 响应生成流程
响应流程图
详细实现
1. 响应头设置
// 响应头设置
public class Http11OutputBuffer extends AbstractOutputBuffer {
@Override
public void sendHeaders() throws IOException {
// 1. 设置状态行
sendStatusLine();
// 2. 设置响应头
for (String name : response.getHeaderNames()) {
String value = response.getHeader(name);
sendHeader(name, value);
}
// 3. 设置空行
sendCRLF();
}
private void sendStatusLine() throws IOException {
// HTTP/1.1 200 OK
String statusLine = "HTTP/1.1 " + response.getStatus() + " " +
response.getMessage() + "\r\n";
write(statusLine.getBytes());
}
}
2. 响应体写入
// 响应体写入
public class Http11OutputBuffer extends AbstractOutputBuffer {
@Override
public void write(byte[] b, int off, int len) throws IOException {
// 1. 检查缓冲区大小
if (len > buffer.length - count) {
flush();
}
// 2. 写入缓冲区
System.arraycopy(b, off, buffer, count, len);
count += len;
// 3. 检查是否需要刷新
if (count >= buffer.length) {
flush();
}
}
@Override
public void flush() throws IOException {
// 1. 写入数据到网络
socketWrapper.write(buffer, 0, count);
// 2. 清空缓冲区
count = 0;
}
}
3. 连接管理
// 连接管理
public class Http11NioProcessor extends AbstractProcessorLight {
@Override
public SocketState process(SocketWrapperBase<NioChannel> socketWrapper)
throws IOException {
// 1. 处理请求
SocketState state = service(socketWrapper);
// 2. 处理响应
if (state == SocketState.OPEN) {
state = processResponse(request, response);
}
// 3. 管理连接
if (state == SocketState.OPEN) {
if (keptAlive) {
// 保持连接
return SocketState.OPEN;
} else {
// 关闭连接
return SocketState.CLOSED;
}
}
return state;
}
}
3.6 性能优化要点
3.6.1 连接优化
连接池配置
<!-- 连接器优化配置 -->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
maxThreads="200"
minSpareThreads="10"
maxSpareThreads="50"
acceptCount="100"
maxConnections="8192"
keepAliveTimeout="60000"
maxKeepAliveRequests="100" />
线程池优化
// 线程池配置
public class StandardThreadExecutor implements Executor {
private final ThreadPoolExecutor executor;
public StandardThreadExecutor() {
// 核心线程数
int corePoolSize = 10;
// 最大线程数
int maximumPoolSize = 200;
// 空闲时间
long keepAliveTime = 60L;
// 时间单位
TimeUnit unit = TimeUnit.SECONDS;
// 工作队列
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(100);
executor = new ThreadPoolExecutor(
corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
}
3.6.2 缓冲区优化
输入缓冲区
// 输入缓冲区配置
public class Http11InputBuffer {
private static final int DEFAULT_BUFFER_SIZE = 8192;
private static final int MAX_BUFFER_SIZE = 65536;
private byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
private int pos = 0;
private int lastValid = 0;
public void expand(int size) {
if (size > MAX_BUFFER_SIZE) {
throw new IllegalArgumentException("Buffer size too large");
}
byte[] newBuffer = new byte[size];
System.arraycopy(buffer, 0, newBuffer, 0, lastValid);
buffer = newBuffer;
}
}
输出缓冲区
// 输出缓冲区配置
public class Http11OutputBuffer {
private static final int DEFAULT_BUFFER_SIZE = 8192;
private static final int MAX_BUFFER_SIZE = 65536;
private byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
private int count = 0;
public void expand(int size) {
if (size > MAX_BUFFER_SIZE) {
throw new IllegalArgumentException("Buffer size too large");
}
byte[] newBuffer = new byte[size];
System.arraycopy(buffer, 0, newBuffer, 0, count);
buffer = newBuffer;
}
}
3.6.3 压缩优化
GZIP 压缩
<!-- 启用压缩 -->
<Connector port="8080" protocol="HTTP/1.1"
compression="on"
compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json" />
压缩实现
// 压缩实现
public class CompressionFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// 检查是否支持压缩
String acceptEncoding = httpRequest.getHeader("Accept-Encoding");
if (acceptEncoding != null && acceptEncoding.contains("gzip")) {
// 启用压缩
httpResponse.setHeader("Content-Encoding", "gzip");
GZIPOutputStream gzipOut = new GZIPOutputStream(response.getOutputStream());
chain.doFilter(request, new GzipResponseWrapper(httpResponse, gzipOut));
} else {
chain.doFilter(request, response);
}
}
}
3.7 本章小结
关键要点
请求处理流程:
- 网络层接收 → 协议解析 → 适配器转换 → 容器路由 → Servlet 调用
- 每个步骤都有明确的职责和接口定义
路由机制:
- Engine → Host → Context → Wrapper → Servlet
- 每层都有对应的路由逻辑和匹配规则
NIO 模型:
- Acceptor 线程接收连接
- Poller 线程处理 I/O 事件
- Worker 线程池处理业务逻辑
性能优化:
- 连接池和线程池配置
- 缓冲区大小优化
- 压缩和缓存策略
配置要点
连接器配置:
- 合理设置线程池参数
- 优化连接超时和保持时间
- 启用压缩和缓存
容器配置:
- 合理设置应用上下文
- 优化 Servlet 映射
- 配置过滤器和监听器
下一步学习
在下一章中,我们将深入探讨 Tomcat 的线程模型与运行方式,了解不同 I/O 模式的特点和适用场景,以及如何根据应用需求选择合适的运行模式。
相关资源:
浙公网安备 33010602011771号