┌─────────────────────────────────────────────────────┐
│ Browser │
└───────────────────┬─────────────────────────────────┘
│ HTTP Request
▼
┌─────────────────────────────────────────────────────┐
│ Connector (HTTP/1.1, AJP, etc.) │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Protocol │ │ Endpoint │ │
│ │ Handler │ │ (NIO/APR) │ │
│ └─────────────┘ └─────────────┘ │
└───────────────────┬─────────────────────────────────┘
│ Request/Response对象封装
▼
┌─────────────────────────────────────────────────────┐
│ Container │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Engine │→ │ Host │→ │ Context │→│
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└───────────────────┬─────────────────────────────────┘
│ Servlet调用
▼
┌─────────────────────────────────────────────────────┐
│ Servlet Container │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Wrapper │→ │ Servlet │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────┘
// 1. 客户端通过Socket连接Tomcat
Socket socket = serverSocket.accept();
// 2. 交给Connector处理
// Connector配置示例 (server.xml)
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
maxThreads="150"
acceptCount="100"/>
步骤2:协议解析
// Http11Processor解析HTTP请求
public class Http11Processor {
// 解析请求行
private void parseRequestLine() {
// GET /index.html HTTP/1.1
method = parseMethod();
uri = parseUri();
protocol = parseProtocol();
}
// 解析请求头
private void parseHeaders() {
// Host: localhost:8080
// Content-Type: application/json
// ...
}
}
// CoyoteAdapter将底层请求转换为Servlet API规范
public class CoyoteAdapter {
public void service(org.apache.coyote.Request req,
org.apache.coyote.Response res) {
// 创建ServletRequest/Response对象
Request request = new Request();
Response response = new Response();
// 填充请求数据
request.setMethod(req.method().toString());
request.setRequestURI(req.requestURI().toString());
request.setProtocol(req.protocol().toString());
// 交给Container处理
connector.getService().getContainer()
.getPipeline().getFirst().invoke(request, response);
}
}
步骤4:容器管道处理
// 四个层级的容器
// 1. Engine - 整个Servlet引擎
// 2. Host - 虚拟主机
// 3. Context - Web应用上下文
// 4. Wrapper - 具体Servlet包装
// 管道阀门处理链
public class StandardEngineValve extends ValveBase {
public void invoke(Request request, Response response) {
// 选择Host
Host host = request.getHost();
// 调用Host的管道
host.getPipeline().getFirst().invoke(request, response);
}
}
步骤5:Servlet匹配与调用
// Mapper组件进行URL模式匹配
public class Mapper {
public void map(Context context,
String uri,
MappingData mappingData) {
// 精确匹配
// 路径匹配
// 扩展名匹配
// 默认Servlet
}
}
// Filter链执行
public class ApplicationFilterChain {
public void doFilter(ServletRequest req,
ServletResponse res) {
// 按配置顺序执行Filter
for (Filter filter : filters) {
filter.doFilter(req, res, this);
}
// 最后调用Servlet
servlet.service(req, res);
}
}
// HttpServlet的分发逻辑
protected void service(HttpServletRequest req,
HttpServletResponse resp) {
String method = req.getMethod();
if (method.equals("GET")) {
doGet(req, resp);
} else if (method.equals("POST")) {
doPost(req, resp);
}
// ... 其他HTTP方法
}
步骤7:生成响应
// 开发者的Servlet实现
public class MyServlet extends HttpServlet {
protected void doGet(HttpServletRequest req,
HttpServletResponse resp) {
// 设置响应头
resp.setContentType("text/html;charset=UTF-8");
resp.setHeader("Cache-Control", "no-cache");
// 获取输出流
PrintWriter out = resp.getWriter();
// 写入响应体
out.println("<html>");
out.println("<body>");
out.println("<h1>Hello World</h1>");
out.println("</body>");
out.println("</html>");
out.flush();
out.close();
}
}
// Response对象处理
public class Response {
// 响应状态行
public void setStatus(int status, String message) {
this.status = status;
this.message = message;
}
// 发送响应
public void finish() {
// 写入状态行
writeStatusLine();
// 写入响应头
writeHeaders();
// 写入响应体
writeBody();
// 刷新缓冲区
flushBuffer();
}
}
步骤9:连接清理
// 连接回收处理
public class Http11Processor {
public void action(ActionCode action, Object param) {
switch (action) {
case CLOSE:
// 关闭连接
endRequest();
recycle();
break;
case COMMIT:
// 提交响应
outputBuffer.commit();
break;
}
}
private void recycle() {
// 重置处理器状态
request.recycle();
response.recycle();
// 放回连接池
}
}
<!-- 三种协议实现 -->
<!-- 1. HTTP/1.1 (默认) -->
<Connector port="8080" protocol="HTTP/1.1"/>
<!-- 2. AJP (Apache JServ Protocol) -->
<Connector port="8009" protocol="AJP/1.3"/>
<!-- 3. HTTP/2 -->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol">
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol"/>
</Connector>
┌─────────────────────────────────────────┐
│ Acceptor Thread (1) │
│ 监听端口,接收新连接 │
└───────────────┬─────────────────────────┘
│ 分配Socket
▼
┌─────────────────────────────────────────┐
│ Poller Threads (N) │
│ 监控Socket可读/可写事件 │
└───────────────┬─────────────────────────┘
│ 交给Worker处理
▼
┌─────────────────────────────────────────┐
│ Worker Threads (M) │
│ 处理HTTP请求,执行业务逻辑 │
└─────────────────────────────────────────┘
// 使用NIO提高并发性能
public class NioEndpoint extends AbstractEndpoint {
// 选择器处理就绪事件
private Poller poller = new Poller();
// 工作线程池
private Executor executor = new ThreadPoolExecutor(
minSpareThreads, maxThreads,
keepAliveTime, TimeUnit.SECONDS,
new LinkedBlockingQueue<>()
);
}
<Connector
port="8080"
protocol="HTTP/1.1"
<!-- 连接参数 -->
connectionTimeout="20000"
maxConnections="10000"
<!-- 线程池参数 -->
maxThreads="200"
minSpareThreads="10"
acceptCount="100"
<!-- 缓冲区参数 -->
maxHttpHeaderSize="8192"
maxPostSize="2097152"
<!-- 性能优化 -->
enableLookups="false"
compression="on"
compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/json"
/>
<Engine name="Catalina" defaultHost="localhost">
<Host name="localhost" appBase="webapps">
<!-- 自动部署 -->
<Context path="/myapp" docBase="/opt/myapp">
<!-- 资源配置 -->
<Resources className="org.apache.catalina.webresources.StandardRoot">
<PreResources base="/shared/lib"
webAppMount="/WEB-INF/lib"/>
</Resources>
<!-- 会话配置 -->
<Manager className="org.apache.catalina.session.StandardManager"
maxActiveSessions="1000"/>
</Context>
</Host>
</Engine>
客户端请求
│
▼
Socket连接建立
│
▼
Acceptor接收连接
│
▼
Poller监控事件
│
▼
Http11Processor解析HTTP
│
▼
CoyoteAdapter转换请求
│
▼
Engine → Host → Context → Wrapper
│
▼
FilterChain执行
│
▼
Servlet.service()调用
│
▼
业务逻辑处理
│
▼
生成HttpServletResponse
│
▼
响应返回客户端
│
▼
连接回收/保持
# 调整连接超时
connectionTimeout=30000
# 适当增加最大连接数
maxConnections=8192
# 优化线程池
maxThreads=500
minSpareThreads=50
# 调整缓冲区大小
socketBuffer=9000
bufferSize=4096
# 禁用DNS查询
enableLookups=false
# 启用压缩
compression=on
compressionMinSize=1024
# 典型Tomcat启动参数
export CATALINA_OPTS="
-server
-Xms2g
-Xmx2g
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:+DisableExplicitGC
-XX:+HeapDumpOnOutOfMemoryError
"
// 查看线程堆栈
public class ThreadDumpUtil {
public static void dumpThreads() {
ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();
for (ThreadInfo ti : threadMxBean.dumpAllThreads(true, true)) {
System.out.println(ti.toString());
}
}
}
<!-- 启用泄漏检测 -->
<Context>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
</Context>
# 启用请求监控
org.apache.tomcat.util.http.ServerCookie.FWD_SLASH_IS_SEPARATOR=false
# 日志记录慢请求
<Valve className="org.apache.catalina.valves.StuckThreadDetectionValve"
threshold="30000"/>
Tomcat的HTTP请求处理是一个复杂的多阶段流水线过程,涉及:
连接管理:通过连接器接收和处理TCP连接 协议解析:将原始字节流解析为HTTP消息 容器处理:通过四级容器架构分发请求 Servlet执行:最终由Servlet生成动态内容 响应返回:将处理结果返回客户端理解这个完整流程对于:
都有重要意义。每个阶段都可以通过配置进行优化,需要根据实际应用场景进行调整。