
1. 什么是 Tomcat?
Apache Tomcat 是一个开源的 Java Servlet 容器 ,实现了 Java EE(现在称为 Jakarta EE)规范中的 Servlet 、JSP (JavaServer Pages)、EL (表达式语言)和 WebSocket 技术。它是由 Apache 软件基金会开发的一款轻量级应用服务器,也是目前最流行的 Java Web 应用服务器。
Tomcat 的架构设计遵循了分层和解耦的原则,整个系统由多个相互协作的组件构成,每个组件负责特定的功能。这种设计使得 Tomcat 既灵活又稳定,可以根据需要替换或扩展各个组件。
最顶层是 Server,代表整个 Tomcat 实例,它包含一个或多个 Service。每个 Service 由若干 Connector 和一个 Engine 组成。Connector 负责处理网络连接,Engine 负责处理请求。Engine 内部包含多个 Host(虚拟主机),每个 Host 包含多个 Context(Web 应用),每个 Context 包含多个 Wrapper(Servlet 包装器)。这种层次化的结构使得 Tomcat 能够在一台服务器上托管多个域名和多个应用,同时保持清晰的隔离。
2. Tomcat 的定位
Java Web 应用架构层次:
┌─────────────────────────────────────┐
│ Java Web 应用 (WAR) │ 开发者编写的业务代码
├─────────────────────────────────────┤
│ Servlet/JSP/EL/WebSocket │ Java Web 规范
├─────────────────────────────────────┤
│ Tomcat 容器 │ Servlet 容器(处理HTTP)
├─────────────────────────────────────┤
│ JVM (Java虚拟机) │ 运行Java字节码
├─────────────────────────────────────┤
│ 操作系统 (Linux/Windows) │
└─────────────────────────────────────┘
3. 与其他应用服务器的对比
| 特性 | Tomcat | Jetty | Undertow | WildFly | WebLogic |
|---|---|---|---|---|---|
| 定位 | 轻量级Servlet容器 | 嵌入式容器 | 高性能容器 | 全栈Java EE | 商业企业级 |
| 规范实现 | Servlet/JSP/EL/WebSocket | Servlet | Servlet | 完整Java EE | 完整Java EE |
| 内存占用 | 中等 | 低 | 低 | 高 | 非常高 |
| 启动速度 | 中等 | 快 | 快 | 慢 | 慢 |
| 配置复杂度 | 简单 | 简单 | 中等 | 复杂 | 复杂 |
| 集群支持 | 基础 | 基础 | 基础 | 完整 | 完整 |
| 管理控制台 | 有 | 无 | 无 | 有 | 有 |
| 开源/商业 | 开源 | 开源 | 开源 | 开源 | 商业 |
| 典型场景 | 中小型Web应用 | 微服务/嵌入式 | 高性能微服务 | 大型企业应用 | 金融/电信 |
Tomcat安装部署
下载安装包
# 环境确定
[root@RS1 ~]# systemctl disable --now httpd
Removed "/etc/systemd/system/multi-user.target.wants/httpd.service".
[root@RS2 ~]# systemctl disable --now httpd
Removed "/etc/systemd/system/multi-user.target.wants/httpd.service".
# 下载安装包
[root@RS1 ~]# wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.115/bin/apache-tomcat-9.0.115.tar.gz
[root@RS2 ~]# wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.115/bin/apache-tomcat-9.0.115.tar.gz
部署tomcat
[root@RS1 ~]# yum install java-1.8.0-openjdk.x86_64 -y
[root@RS1 ~]# tar zxf apache-tomcat-9.0.115.tar.gz -C /usr/local
[root@RS1 ~]# cd /usr/local/
[root@RS1 local]# ls
apache-tomcat-9.0.115 etc include lib64 sbin src
bin games lib libexec share
[root@RS1 local]# mv apache-tomcat-9.0.115/ tomcat
[root@RS1 local]# cd tomcat/
[root@RS1 tomcat]# ls
bin CONTRIBUTING.md logs RELEASE-NOTES webapps
BUILDING.txt lib NOTICE RUNNING.txt work
conf LICENSE README.md temp
[root@RS1 tomcat]# cd /usr/local/tomcat/bin/
[root@RS1 bin]# ./startup.sh
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:
Tomcat started.
[root@RS1 bin]# netstat -antlupe | grep 8080
tcp6 0 0 :::8080 :::* LISTEN 0 57753 12479/java
制作tomcat的启动脚本
[root@RS1 bin]# vim /usr/local/tomcat/conf/tomcat.conf
JAVA_HOME=/etc/alternatives/jre
[root@RS1 bin]# vim /lib/systemd/system/tomcat.service
[Unit]
Description=Tomcat
#After=syslog.target network.target remote-fs.target nss-lookup.target
After=syslog.target network.target
[Service]
Type=forking
EnvironmentFile=/usr/local/tomcat/conf/tomcat.conf
ExecStart=/usr/local/tomcat/bin/startup.sh
ExecStop=/usr/local/tomcat/bin/shutdown.sh
PrivateTmp=true
User=tomcat
Group=tomcat
[Install]
WantedBy=multi-user.target
[root@RS1 bin]# useradd -s /sbin/nologin -M tomcat
[root@RS1 bin]# chown tomcat.tomcat /usr/local/tomcat/ -R
[root@RS1 bin]# systemctl daemon-reload
[root@RS1 bin]# systemctl enable --now tomcat
[root@RS1 bin]# netstat -antlupe | grep java
tcp6 0 0 127.0.0.1:8005 :::* LISTEN 1000 139979 10682/java
tcp6 0 0 :::8080 :::* LISTEN 1000 140563 10682/java
Tomcat 的整体目录结构
当你下载并解压 Tomcat,或者通过包管理器安装后,会得到一个固定的目录结构。理解这个结构是管理 Tomcat 的基础。Tomcat 的目录设计遵循了清晰的分离原则,将可执行文件、配置文件、日志文件和应用文件分别存放。
典型的 Tomcat 安装目录(以 /usr/local/tomcat 或 /opt/tomcat 为例)包含以下一级子目录:
tomcat/
├── bin/ # 启动、关闭脚本和可执行文件
├── conf/ # 核心配置文件所在目录
├── lib/ # Tomcat 和所有应用共享的 Java 类库(JAR 包)
├── logs/ # 日志文件输出目录
├── temp/ # 临时文件存放目录
├── webapps/ # Web 应用部署目录
└── work/ # JSP 编译后的 Servlet 类文件存放目录
结合反向代理实现 tomcat 部署

为什么需要反向代理 + Tomcat 架构?
1.1 Tomcat 单独运行的局限性
虽然 Tomcat 本身就是一个功能完整的 Web 服务器,能够直接处理 HTTP 请求,但在生产环境中,单独使用 Tomcat 会面临以下几个挑战:
静态资源处理效率不高:Tomcat 是 Java 应用服务器,它的核心优势是处理动态内容(Servlet、JSP)。对于静态资源(HTML、CSS、JavaScript、图片等),Tomcat 的处理方式相对低效,每个静态请求都会占用一个线程,而这些线程本可以用于处理动态业务逻辑。
并发连接处理能力受限:Tomcat 的默认配置下,能够同时处理的连接数有限。当面临高并发访问时,Tomcat 容易成为瓶颈,导致请求排队甚至拒绝服务。
安全性方面的不足:直接暴露 Tomcat 给外部网络存在安全风险。Tomcat 的版本信息、错误页面细节可能被攻击者利用,而且 Tomcat 本身对某些类型的攻击(如慢速连接攻击)的防护能力较弱。
负载均衡能力有限:单台 Tomcat 无法水平扩展,当流量增长时,只能通过垂直扩展(增加硬件配置)来应对,成本高昂且有上限。
SSL/TLS 处理消耗资源:HTTPS 加密解密是 CPU 密集型操作,如果由 Tomcat 直接处理,会占用大量计算资源,影响业务处理能力。
1.2 反向代理带来的价值
引入反向代理(如 Nginx、Apache HTTP Server、HAProxy)后,上述问题都能得到有效解决:
动静分离:反向代理擅长处理静态资源,可以将静态请求直接响应,只将动态请求转发给后端的 Tomcat。这样既减轻了 Tomcat 的负担,又提升了静态资源的访问速度。
负载均衡:反向代理可以将请求分发到多个 Tomcat 节点,实现水平扩展。当业务增长时,只需要增加 Tomcat 节点,反向代理会自动将流量分散到所有节点。
安全防护:反向代理可以作为一道屏障,隐藏后端 Tomcat 的真实信息。它可以拦截恶意请求,提供访问控制,防御 DDoS 攻击,保护后端服务。
SSL 终结:将 HTTPS 解密工作交给反向代理,Tomcat 只需处理明文的 HTTP 请求。这样不仅减轻了 Tomcat 的 CPU 负担,还可以集中管理 SSL 证书。
缓存加速:反向代理可以缓存动态生成的页面内容,当相同的请求再次到达时,直接返回缓存结果,无需 Tomcat 重新处理。
连接管理:反向代理可以维持与客户端的连接,同时通过连接池与 Tomcat 通信,减少 Tomcat 的连接建立开销。
tomcat负载均衡实现
root@Nginx conf.d\]# vim vhosts.conf upstream tomcat { hash cookie_JSESSIONID; server 172.25.254.10:8080; server 172.25.254.20:8080; } server { listen 80; server_name app.timinglee.org; location \~\* \\.jsp { proxy_pass http://tomcat; } } \[root@Nginx conf.d\]# nginx -s reload #在windows浏览器中访问 app.timinglee.org/test.jsp; #在windows的另外一个浏览器中访问 app.timinglee.org/test.jsp
Memcached
什么是 Memcached?
Memcached 是一个高性能、分布式内存对象缓存系统 ,最初由 Brad Fitzpatrick 为 LiveJournal 网站开发,现在已被全球成千上万个网站采用。它的核心思想是通过在内存中缓存数据和对象,减少对数据库的访问次数,从而加速动态 Web 应用。
memcached的安装与启动
root@RS1 jar\]# dnf install memcached \[root@RS2 \~\]# dnf install memcached -y \[root@RS1 \~\]# vim /etc/sysconfig/memcached \[root@RS2 \~\]# vim /etc/sysconfig/memcached PORT="11211" USER="memcached" MAXCONN="1024" CACHESIZE="64" OPTIONS="-l 0.0.0.0,::1" \[root@RS1+2 \~\]# netstat -antluple \| grep memcached tcp 0 0 0.0.0.0:11211 0.0.0.0:\* LISTEN 988 142615 35756/memcached tcp6 0 0 ::1:11211 :::\* LISTEN 988 142616 35756/memcached
[root@RS1 ]# vim /usr/local/tomcat/conf/context.xml
<Context>
<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:172.25.254.10:11211,n2:172.25.254.20:11211"
failoverNodes="n1"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
</Context>
[root@RS2 ]# vim /usr/local/tomcat/conf/context.xml
<Context>
<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:172.25.254.10:11211,n2:172.25.254.20:11211"
failoverNodes="n2"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
</Context>
[root@RS1 ~]# systemctl restart tomcat.service
[root@RS2 ~]# systemctl restart tomcat.service