Tomcat 专题:从基础架构到性能调优与 WebSocket 实战 📅 2026/8/15 7:58:11 1. 课程内容介绍本专题围绕 Tomcat 展开内容涵盖基础概念、整体架构、核心组件、服务器配置、JVM 调优、集群部署、安全加固以及 WebSocket 实战案例。课程从源码层面剖析 Tomcat 的启动流程、请求处理流程和 Jasper 引擎编译原理帮助读者深入理解 Tomcat 的内部工作机制并掌握生产环境下的配置与调优方法。2. Tomcat 基础2.1 Web 相关概念Web 开发中常见的概念包括 HTTP 协议、Web 服务器、Servlet 容器等。HTTP 是浏览器与服务器之间通信的协议Web 服务器负责接收请求并返回静态资源而 Servlet 容器则负责加载和管理 Servlet处理动态请求。Tomcat 既是一个 Web 服务器也是一个 Servlet 容器。2.2 常见的 Web 服务器软件常见的 Web 服务器软件包括 Apache HTTP Server、Nginx、IIS 以及 Tomcat。其中 Apache 和 Nginx 主要处理静态资源和高并发转发Tomcat 则专注于 Java Servlet 和 JSP 的动态处理。在实际项目中常使用 Nginx 作为反向代理将动态请求转发给 Tomcat。2.3 Tomcat 安装及目录结构Tomcat 的安装非常简单只需下载对应版本的压缩包并解压即可。解压后的目录结构如下bin存放启动和关闭脚本如 startup.sh、shutdown.sh。conf存放配置文件如 server.xml、web.xml。lib存放 Tomcat 运行所需的 jar 包。logs存放运行日志。webapps存放部署的 Web 应用。work存放 JSP 编译后的 class 文件。2.4 Tomcat 源码部署运行为了深入理解 Tomcat 的源码可以将 Tomcat 源码导入 IDE 进行调试。首先从官网下载源码包然后使用 Maven 构建项目。构建完成后运行 org.apache.catalina.startup.Bootstrap 类的 main 方法即可启动 Tomcat。通过源码调试可以清晰地看到 Tomcat 的启动流程和请求处理流程。3. Tomcat 架构3.1 HTTP 工作流程一次完整的 HTTP 请求处理流程如下浏览器发起请求经过网络传输到达 Tomcat 的 ConnectorConnector 将请求解析为 Request 对象然后交给 Container 处理。Container 中的 Engine、Host、Context 逐级匹配最终定位到具体的 Servlet。Servlet 处理完成后将 Response 返回给 Connector再由 Connector 将响应写回浏览器。3.2 Tomcat 整体架构Tomcat 的整体架构由 Connector 和 Container 两大部分组成。Connector 负责处理网络连接和协议解析Container 负责处理 Servlet 请求。一个 Tomcat 实例可以配置多个 Connector如 HTTP、HTTPS、AJP它们共享同一个 Container。Container 采用分层结构从上到下依次为 Engine、Host、Context、Wrapper。3.3 Coyote 连接器架构Coyote 是 Tomcat 的连接器框架负责处理底层网络通信。它支持多种协议HTTP/1.1、HTTP/2、AJP和多种 IO 模型BIO、NIO、NIO2、APR。Coyote 的核心组件包括 Endpoint、Processor 和 Adapter。Endpoint 负责监听端口和接收连接Processor 负责解析协议Adapter 则将请求适配给 Container。3.4 Coyote 连接器组件Coyote 连接器的主要组件如下Endpoint负责底层 Socket 的监听和读写提供 NIO 和 BIO 两种实现。Processor负责将字节流解析为 HttpServletRequest 对象。Adapter将 Processor 解析出的请求交给 Container 处理是连接器与容器之间的桥梁。ProtocolHandler封装了 Endpoint 和 Processor对外提供统一的协议处理入口。3.5 Catalina 容器结构Catalina 是 Tomcat 的 Servlet 容器实现其核心是 Container 接口。Container 有四种实现Engine、Host、Context、Wrapper它们之间是父子关系。Engine 代表整个 Catalina 引擎Host 代表一个虚拟主机Context 代表一个 Web 应用Wrapper 代表一个 Servlet。每个 Container 都包含 Pipeline 和 Valve用于处理请求。3.6 启动流程Tomcat 的启动流程从 Bootstrap 的 main 方法开始主要步骤如下初始化类加载器加载 catalina.jar 等核心类。创建 Catalina 实例并加载 server.xml 配置文件。根据配置创建 StandardServer、StandardService、Connector 和 Engine 等组件。调用各组件的 init 和 start 方法完成初始化并启动。注册关闭钩子等待关闭命令。3.7 启动流程 - 涉及组件介绍启动过程中涉及的核心组件包括BootstrapTomcat 的入口类负责创建 Catalina 并启动。Catalina负责解析 server.xml管理 Server 的生命周期。StandardServer代表整个 Tomcat 服务器管理多个 Service。StandardService包含一个 Engine 和多个 Connector。StandardEngine代表 Servlet 引擎管理多个 Host。3.8 启动流程 - 源码跟踪通过源码跟踪可以更清晰地理解启动流程。以下是 Bootstrap 启动的核心代码逻辑public class Bootstrap { public static void main(String[] args) { // 1. 初始化类加载器 // 创建 Tomcat 自定义的类加载器体系用于加载 catalina.jar 等核心类 initClassLoaders(); // 2. 创建 Catalina 实例 // Catalina 是 Tomcat 的核心容器负责解析配置和管理生命周期 Catalina catalina new Catalina(); // 3. 加载 server.xml 配置 // 解析 conf/server.xml根据配置创建 Server、Service、Connector、Engine 等组件 catalina.load(); // 4. 启动 Tomcat // 调用各组件的 start 方法完成初始化并开始对外提供服务 catalina.start(); // 5. 注册关闭钩子 // 当 JVM 收到关闭信号时自动调用 catalina.stop() 优雅关闭 Tomcat Runtime.getRuntime().addShutdownHook(new Thread(() - { catalina.stop(); })); // 6. 等待关闭 // 主线程阻塞等待直到收到 SHUTDOWN 命令或 JVM 退出 catalina.await(); } }3.9 请求处理流程请求处理流程是 Tomcat 的核心机制。当请求到达 Connector 后经过以下步骤Endpoint 接收 Socket 连接并将连接交给 Processor。Processor 解析 HTTP 请求生成 Request 和 Response 对象。Adapter 将 Request 和 Response 交给 Container。Engine 的 Pipeline 依次执行 Valve最终将请求路由到对应的 Host。Host 再路由到 ContextContext 再路由到具体的 WrapperServlet。Servlet 执行 service 方法生成响应并返回。3.10 请求处理流程 - 源码跟踪以下是请求处理的核心代码逻辑展示了 Connector 如何将请求交给 Containerpublic class CoyoteAdapter implements Adapter { Override public void service(Request request, Response response) { // 1. 将 Coyote 请求转换为 Catalina 请求 // 从 Request 的 Note 中取出之前由 Connector 存入的 Catalina Request 对象 org.apache.catalina.connector.Request catalinaRequest (org.apache.catalina.connector.Request) request.getNote( ADAPTER_NOTES); // 2. 获取 Container 并调用其 Pipeline // 通过 Request 反向拿到 Connector再拿到 Service 和 Engine Connector connector catalinaRequest.getConnector(); Service service connector.getService(); Engine engine service.getContainer(); // 3. 调用 Engine 的 Pipeline 处理请求 // Pipeline 中的 Valve 链会依次执行最终把请求路由到对应的 Servlet engine.getPipeline().getFirst().invoke( catalinaRequest, catalinaResponse); } }4. Jasper 引擎4.1 介绍Jasper 是 Tomcat 的 JSP 引擎负责将 JSP 文件编译为 Servlet 源码再编译为 class 文件。JSP 本质上是一个 ServletJasper 的作用就是将 JSP 中的 HTML 和 Java 代码混合内容转换为纯 Java 代码。4.2 编译方式 - 流程源码Jasper 的编译流程如下当 JSP 文件首次被请求时Jasper 会检查 JSP 文件是否被修改过。如果 JSP 文件不存在对应的 class 文件或者 JSP 文件被修改过则触发编译。Jasper 将 JSP 文件解析为 AST抽象语法树。根据 AST 生成 Java 源码写入 work 目录。使用 javac 将 Java 源码编译为 class 文件。加载 class 文件创建 Servlet 实例并执行。4.3 编译原理Jasper 编译的核心是 JspServlet。当请求到达时JspServlet 会调用 JspCompilationContext 的 compile 方法进行编译。编译过程中Parser 负责解析 JSP 文件Generator 负责生成 Java 源码。生成的 Servlet 类继承自 HttpJspBase其 _jspService 方法包含了 JSP 页面的所有逻辑。5. 服务器配置5.1 介绍Server, Serviceserver.xml 是 Tomcat 的核心配置文件。最顶层的元素是 Server代表整个 Tomcat 实例。Server 内部包含多个 Service每个 Service 包含一个 Engine 和多个 Connector。一个典型的配置如下Server port8005 shutdownSHUTDOWN Service nameCatalina Connector port8080 protocolHTTP/1.1 connectionTimeout20000 redirectPort8443 / Engine nameCatalina defaultHostlocalhost Host namelocalhost appBasewebapps / /Engine /Service /Server5.2 ExecutorExecutor 是 Tomcat 的线程池配置用于管理处理请求的线程。通过配置 Executor可以控制最大线程数、最小空闲线程数、队列长度等参数。示例配置如下Executor nametomcatThreadPool namePrefixcatalina-exec- maxThreads200 minSpareThreads25 maxQueueSize100 / Connector port8080 protocolHTTP/1.1 executortomcatThreadPool /5.3 ConnectorConnector 负责处理客户端连接。常用的配置参数包括 port端口、protocol协议、connectionTimeout连接超时、redirectPort重定向端口、maxThreads最大线程数等。对于 HTTPS还需要配置 SSL 证书相关参数。5.4 Engine, HostEngine 是 Servlet 引擎负责处理所有请求。Host 代表一个虚拟主机通过域名区分。一个 Engine 可以包含多个 Host每个 Host 可以包含多个 Context。配置示例Engine nameCatalina defaultHostlocalhost Host namelocalhost appBasewebapps unpackWARstrue autoDeploytrue Context path/myapp docBasemyapp / /Host /Engine5.5 ContextContext 代表一个 Web 应用。每个 Context 对应一个应用目录或 WAR 包。Context 的配置可以放在 server.xml 中也可以放在应用的 META-INF/context.xml 中。常用属性包括 path访问路径、docBase应用目录、reloadable是否热部署等。6. Web 应用配置6.1 今日内容本节介绍 Web 应用的核心配置包括 context-param、会话配置、Servlet/Listener/Filter 配置、欢迎页面和错误页面等。这些配置都写在 web.xml 文件中。6.2 context-paramcontext-param 用于配置全局参数可以在整个应用中通过 ServletContext 获取。配置示例context-param param-nameglobalConfig/param-name param-valueconfig-value/param-value /context-param在 Java 代码中获取// 通过 ServletContext 获取 web.xml 中配置的全局参数 // getInitParameter 返回指定名称的 context-param 参数值 String value getServletContext() .getInitParameter(globalConfig);6.3 会话配置 session-configsession-config 用于配置会话超时时间。单位是分钟默认值为 30 分钟。配置示例session-config session-timeout30/session-timeout cookie-config http-onlytrue/http-only /cookie-config /session-config6.4 servlet-listener-filterweb.xml 中可以配置 Servlet、Listener 和 Filter。Servlet 用于处理请求Listener 用于监听应用事件Filter 用于拦截请求。配置示例servlet servlet-nameHelloServlet/servlet-name servlet-classcom.example.HelloServlet/servlet-class /servlet servlet-mapping servlet-nameHelloServlet/servlet-name url-pattern/hello/url-pattern /servlet-mapping filter filter-nameEncodingFilter/filter-name filter-classcom.example.EncodingFilter/filter-class /filter filter-mapping filter-nameEncodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping listener listener-classcom.example.AppListener/listener-class /listener6.5 欢迎页面和错误页面欢迎页面是访问应用根路径时默认显示的页面错误页面用于处理 HTTP 错误码和异常。配置示例welcome-file-list welcome-fileindex.html/welcome-file welcome-fileindex.jsp/welcome-file /welcome-file-list error-page error-code404/error-code location/error/404.html/location /error-page error-page exception-typejava.lang.Exception/exception-type location/error/error.jsp/location /error-page7. Tomcat 管理配置7.1 host-managerhost-manager 是 Tomcat 自带的虚拟主机管理应用用于管理 Host。访问地址为 http://localhost:8080/host-manager。默认情况下只有配置了 manager-gui 角色的用户才能访问。在 conf/tomcat-users.xml 中配置用户role rolenameadmin-gui / user usernameadmin passwordadmin123 rolesadmin-gui /7.2 managermanager 应用用于管理 Web 应用的部署、启动、停止和卸载。访问地址为 http://localhost:8080/manager。配置用户role rolenamemanager-gui / user usernametomcat passwordtomcat123 rolesmanager-gui /8. JVM 配置8.1 内存参数配置JVM 内存参数通过 CATALINA_OPTS 环境变量配置。常见参数包括-Xms初始堆内存大小。-Xmx最大堆内存大小。-XX:PermSize永久代初始大小JDK 8 之前。-XX:MaxPermSize永久代最大大小JDK 8 之前。-XX:MetaspaceSize元空间初始大小JDK 8 之后。-XX:MaxMetaspaceSize元空间最大大小JDK 8 之后。在 bin/catalina.sh 中配置示例CATALINA_OPTS-Xms512m -Xmx1024m -XX:MetaspaceSize128m -XX:MaxMetaspaceSize256m9. Tomcat 集群9.1 介绍及准备工作Tomcat 集群用于提高系统的可用性和并发处理能力。集群中的每个节点运行相同的应用通过负载均衡器分发请求。准备工作包括准备多台服务器、安装 Tomcat、部署相同的应用、配置负载均衡器如 Nginx。9.2 负载均衡策略常见的负载均衡策略包括轮询将请求依次分发到每个节点。加权轮询根据节点性能分配不同的权重。IP 哈希根据客户端 IP 的哈希值分发请求保证同一 IP 的请求始终到达同一节点。最少连接将请求分发到当前连接数最少的节点。9.3 session 共享问题及方案在集群环境中用户的请求可能被分发到不同的节点导致 Session 不一致。解决方案包括Session 复制节点之间同步 Session 数据。Session 粘滞通过负载均衡策略将同一用户的请求始终分发到同一节点。集中式 Session 存储将 Session 存储在 Redis 等外部存储中。9.4 Session 复制Session 复制通过配置 Cluster 实现。在 server.xml 的 Engine 中添加 Cluster 配置Engine nameCatalina defaultHostlocalhost Cluster classNameorg.apache.catalina.ha.tcp.SimpleTcpCluster Manager classNameorg.apache.catalina.ha.session.DeltaManager expireSessionsOnShutdownfalse notifyListenersOnReplicationtrue / Channel classNameorg.apache.catalina.tribes.group.GroupChannel Membership classNameorg.apache.catalina.tribes.membership.McastService address228.0.0.4 port45564 frequency500 dropTime3000 / Receiver classNameorg.apache.catalina.tribes.transport.nio.NioReceiver addressauto port4000 autoBind100 selectorTimeout5000 / /Channel /Cluster /Engine9.5 SSO 解决 Session 共享问题SSO单点登录是解决 Session 共享的另一种方案。用户只需登录一次即可访问多个系统。常见的实现方式包括 CAS、OAuth2 等。在 Tomcat 中可以通过配置 SSO Valve 实现同一虚拟主机下的单点登录Host namelocalhost appBasewebapps Valve classNameorg.apache.catalina.authenticator.SingleSignOn / /Host10. Tomcat 安全10.1 配置安全Tomcat 安全配置包括修改默认端口和管理密码。禁用不需要的 Connector 和协议。配置访问控制限制管理应用的访问 IP。定期更新 Tomcat 版本修复已知漏洞。删除默认的示例应用如 examples、docs。10.2 传输安全传输安全主要通过 HTTPS 实现。HTTPS 使用 SSL/TLS 协议加密传输数据防止数据被窃听和篡改。配置 HTTPS 需要生成 SSL 证书并在 Connector 中配置。10.3 HTTPS 协议配置使用 keytool 生成自签名证书keytool -genkeypair -alias tomcat -keyalg RSA -keysize 2048 -validity 365 -keystore tomcat.keystore在 server.xml 中配置 HTTPS ConnectorConnector port8443 protocolorg.apache.coyote.http11.Http11NioProtocol maxThreads150 SSLEnabledtrue SSLHostConfig Certificate certificateKeystoreFileconf/tomcat.keystore typeRSA / /SSLHostConfig /Connector11. Tomcat 性能调优11.1 性能测试性能测试是调优的前提。常用的压测工具包括 Apache JMeter、abApache Bench等。通过压测可以获取吞吐量、响应时间、错误率等指标为调优提供依据。11.2 性能测试结果说明性能测试结果通常包括以下指标吞吐量单位时间内处理的请求数。平均响应时间所有请求的平均处理时间。错误率失败请求占总请求的比例。并发数同时处理的请求数量。11.3 JVM 内存参数调优JVM 内存调优的核心是合理设置堆内存大小。堆内存过小会导致频繁 GC过大则可能导致内存溢出。建议将 -Xms 和 -Xmx 设置为相同值避免堆大小动态调整带来的性能开销。示例CATALINA_OPTS-Xms1024m -Xmx1024m -XX:MetaspaceSize256m -XX:MaxMetaspaceSize512m11.4 JVM 垃圾收集器介绍常见的垃圾收集器包括Serial GC单线程收集器适合单核 CPU 和小内存场景。Parallel GC多线程收集器适合多核 CPU 和高吞吐量场景。CMS GC并发标记清除收集器适合低延迟场景。G1 GC分区式收集器兼顾吞吐量和延迟适合大内存场景。11.5 垃圾收集器配置调整在 JDK 8 中可以通过以下参数指定垃圾收集器# 使用 G1 收集器 CATALINA_OPTS-XX:UseG1GC -XX:MaxGCPauseMillis200 使用 Parallel 收集器 CATALINA_OPTS-XX:UseParallelGC -XX:ParallelGCThreads411.6 连接器配置调整Connector 的配置对性能影响很大。关键参数包括 maxThreads最大线程数、acceptCount等待队列长度、connectionTimeout连接超时等。示例Connector port8080 protocolHTTP/1.1 maxThreads400 acceptCount200 connectionTimeout20000 minSpareThreads50 maxKeepAliveRequests100 /12. WebSocket12.1 介绍WebSocket 是一种全双工通信协议允许服务器主动向客户端推送消息。与 HTTP 不同WebSocket 在建立连接后客户端和服务器之间可以随时互相发送消息非常适合实时通信场景如聊天室、在线游戏、实时通知等。12.2 Tomcat 的支持Tomcat 从 7.0.27 版本开始支持 WebSocket从 8.0 版本开始支持 JSR-356Java WebSocket 规范。使用 Tomcat 开发 WebSocket 应用只需实现 WebSocket 注解或继承相关类即可。12.3 案例 - 需求及流程分析本案例实现一个简单的在线聊天室。需求包括用户登录、实时消息推送、在线用户列表、用户上下线通知。流程如下用户通过登录页面输入用户名登录。登录成功后建立 WebSocket 连接。服务器维护在线用户列表并广播用户上线消息。用户发送消息服务器将消息广播给所有在线用户。用户关闭页面时WebSocket 连接断开服务器广播用户下线消息。12.4 案例 - 准备工作创建 Maven Web 项目添加依赖dependency groupIdjavax.websocket/groupId artifactIdjavax.websocket-api/artifactId version1.1/version scopeprovided/scope /dependency12.5 案例 - 登录功能创建登录页面 login.jsp% page contentTypetext/html;charsetUTF-8 % html head title聊天室登录/title /head body form actionlogin methodpost 用户名input typetext nameusername / input typesubmit value登录 / /form /body /html创建登录 Servlet// 使用注解方式注册 Servlet映射到 /login 路径 WebServlet(/login) public class LoginServlet extends HttpServlet { Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 1. 获取表单提交的用户名参数 String username req.getParameter(username); // 2. 校验用户名是否为空去除首尾空格后判断 if (username ! null !username.trim().isEmpty()) { // 3. 用户名合法创建会话并保存用户名 HttpSession session req.getSession(); session.setAttribute(username, username); // 4. 重定向到聊天页面 resp.sendRedirect(chat.jsp); } else { // 5. 用户名非法返回登录页重新输入 resp.sendRedirect(login.jsp); } } }12.6 案例 - OnOpen创建 WebSocket 端点类 ChatEndpoint使用 ServerEndpoint 注解// 声明 WebSocket 端点映射到 /chat 路径 ServerEndpoint(/chat) public class ChatEndpoint { // 线程安全的在线用户会话集合保存所有已连接的 Session private static final SetSession clients Collections.synchronizedSet(new HashSet()); // 当客户端建立 WebSocket 连接时自动调用 OnOpen public void onOpen(Session session) { // 1. 将新会话加入在线用户集合 clients.add(session); // 2. 构造上线通知消息 String message 用户 session.getId() 上线了; // 3. 广播给所有在线用户 broadcast(message); } // 向所有在线用户广播消息 private void broadcast(String message) { synchronized (clients) { for (Session client : clients) { try { // 通过 BasicRemote 发送文本消息 client.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } } } }12.7 案例 - OnOpen 测试启动 Tomcat访问登录页面输入用户名登录后进入聊天页面。打开多个浏览器窗口可以看到每个用户上线时所有窗口都会收到上线通知。12.8 案例 - OnMessage 分析OnMessage 注解的方法用于处理客户端发送的消息。在聊天室中服务器收到消息后需要将消息广播给所有在线用户。12.9 案例 - OnMessage 功能实现在 ChatEndpoint 中添加消息处理方法OnMessage public void onMessage(String message, Session session) { String username (String) session.getUserProperties() .get(username); String fullMessage username message; broadcast(fullMessage); }12.10 案例 - OnMessage 功能测试在聊天页面中输入消息并发送所有在线用户的聊天窗口都会实时显示该消息。测试结果验证了 WebSocket 的全双工通信能力。12.11 案例 - OnClose 及 OnError 介绍OnClose 注解的方法在连接关闭时调用用于清理资源。OnError 注解的方法在发生错误时调用。在聊天室中当用户关闭页面时需要从在线用户集合中移除该会话并广播下线消息OnClose public void onClose(Session session) { clients.remove(session); String message 用户 session.getId() 下线了; broadcast(message); } OnError public void onError(Session session, Throwable error) { error.printStackTrace(); clients.remove(session); }13. 总结本专题系统性地介绍了 Tomcat 的核心知识从基础概念、整体架构到源码级别的启动流程和请求处理流程再到服务器配置、JVM 调优、集群部署、安全加固和 WebSocket 实战。通过本专题的学习读者可以深入理解 Tomcat 的内部机制掌握生产环境下的配置与调优方法并具备使用 WebSocket 开发实时应用的能力。