一、Tomcat 概述
1.1 什么是 Tomcat
Apache Tomcat 是一个开源的 Java Servlet 容器,实现了 Java Servlet、JavaServer Pages (JSP)、Java Expression Language 和 Java WebSocket 技术。
1.2 Tomcat 版本对照
| Tomcat 版本 | Servlet 规范 | JSP 规范 | EL 规范 | WebSocket | JDK 要求 |
|---|---|---|---|---|---|
| 10.x | 5.0 | 3.0 | 4.0 | 2.0 | JDK 11+ |
| 9.x | 4.0 | 2.3 | 3.0 | 1.1 | JDK 8+ |
| 8.x | 3.1 | 2.3 | 3.0 | 1.1 | JDK 7+ |
| 7.x | 3.0 | 2.2 | 2.2 | - | JDK 6+ |
二、Tomcat 安装与部署
2.1 环境准备
# 1. 安装 JDK(以 JDK 11 为例)
# Ubuntu/Debian
sudo apt update
sudo apt install openjdk-11-jdk
# CentOS/RHEL
sudo yum install java-11-openjdk-devel
# 验证安装
java -version
javac -version
# 2. 设置 JAVA_HOME 环境变量
# Linux
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH
# Windows(系统属性 → 环境变量)
# 添加 JAVA_HOME 变量:C:\Program Files\Java\jdk-11.0.x
2.2 Tomcat 安装
2.2.1 Linux 安装
# 1. 下载 Tomcat
wget https://downloads.apache.org/tomcat/tomcat-9/v9.0.xx/bin/apache-tomcat-9.0.xx.tar.gz
# 2. 解压
tar -xzf apache-tomcat-9.0.xx.tar.gz -C /opt/
sudo mv /opt/apache-tomcat-9.0.xx /opt/tomcat
# 3. 创建专用用户
sudo useradd -r -m -U -d /opt/tomcat -s /bin/false tomcat
sudo chown -R tomcat: /opt/tomcat
# 4. 设置服务脚本
# 创建 systemd 服务文件
sudo vi /etc/systemd/system/tomcat.service
tomcat.service 文件内容:
[Unit]
Description=Apache Tomcat Web Application Container
After=network.target
[Service]
Type=forking
User=tomcat
Group=tomcat
Environment="JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64"
Environment="JAVA_OPTS=-Djava.security.egd=file:///dev/urandom"
Environment="CATALINA_BASE=/opt/tomcat"
Environment="CATALINA_HOME=/opt/tomcat"
Environment="CATALINA_PID=/opt/tomcat/temp/tomcat.pid"
Environment="CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC"
ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh
RestartSec=10
Restart=always
[Install]
WantedBy=multi-user.target
2.2.2 Windows 安装
# 1. 下载并解压到 C:\tomcat
# 2. 设置环境变量
SET CATALINA_HOME=C:\tomcat
SET JAVA_HOME=C:\Program Files\Java\jdk-11.0.x
# 3. 安装服务(可选)
# 以管理员身份运行 CMD
cd %CATALINA_HOME%\bin
service.bat install
# 4. 启动服务
net start Tomcat9
2.3 目录结构详解
tomcat/
├── bin/ # 执行脚本
│ ├── startup.sh # 启动脚本
│ ├── shutdown.sh # 停止脚本
│ ├── catalina.sh # 核心启动脚本
│ └── version.sh # 版本查看
├── conf/ # 配置文件
│ ├── server.xml # 主配置文件
│ ├── web.xml # 全局 web 应用配置
│ ├── context.xml # 全局 Context 配置
│ └── tomcat-users.xml # 用户管理
├── lib/ # 共享类库
├── logs/ # 日志文件
│ ├── catalina.out # 控制台输出
│ ├── localhost_access_log # 访问日志
│ └── catalina.yyyy-mm-dd.log
├── webapps/ # 应用部署目录
│ ├── ROOT/ # 根应用
│ ├── docs/ # 文档
│ ├── examples/ # 示例
│ └── manager/ # 管理界面
├── work/ # JSP 编译文件
└── temp/ # 临时文件
2.4 应用部署方式
2.4.1 自动部署
# 1. WAR 包部署
cp application.war /opt/tomcat/webapps/
# Tomcat 会自动解压并部署
# 2. 目录部署
mkdir /opt/tomcat/webapps/myapp
# 将 WEB-INF 和静态文件放入
2.4.2 手动部署 - context.xml
<!-- 在 conf/Catalina/localhost/ 创建 myapp.xml -->
<Context
path="/myapp"
docBase="/opt/webapps/myapp"
reloadable="true"
crossContext="false">
<!-- 数据库连接池配置 -->
<Resource name="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource"
maxTotal="100"
maxIdle="30"
maxWaitMillis="10000"
username="root"
password="password"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/testdb"/>
</Context>
2.4.3 热部署配置
<!-- server.xml 中添加 -->
<Host name="localhost"
appBase="webapps"
unpackWARs="true"
autoDeploy="true"
deployOnStartup="true"
deployIgnore=".*\.(svn|git)">
<Context path="" docBase="myapp" reloadable="true" />
</Host>
三、配置文件详解
3.1 server.xml - 主配置文件
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<!-- 监听器配置 -->
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- 全局资源 -->
<GlobalNamingResources>
<Resource name="UserDatabase"
auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<!-- 服务 -->
<Service name="Catalina">
<!-- 连接器配置 -->
<Connector port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
maxThreads="150"
minSpareThreads="25"
maxConnections="10000"
acceptCount="100"
redirectPort="8443"
compression="on"
compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/json"
URIEncoding="UTF-8"
enableLookups="false"
server="Apache Tomcat"/>
<!-- SSL 配置 -->
<Connector port="8443"
protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150"
SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/keystore.jks"
certificateKeystorePassword="changeit"
type="RSA" />
</SSLHostConfig>
</Connector>
<!-- AJP 连接器(用于 Apache HTTPD 集成) -->
<Connector port="8009"
protocol="AJP/1.3"
redirectPort="8443" />
<!-- 引擎 -->
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">
<!-- 集群配置 -->
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster">
<!-- 详细配置见集群章节 -->
</Cluster>
<!-- 主机 -->
<Host name="localhost"
appBase="webapps"
unpackWARs="true"
autoDeploy="true">
<!-- 访问日志阀门 -->
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="localhost_access_log"
suffix=".txt"
pattern="%h %l %u %t "%r" %s %b %D"
requestAttributesEnabled="true"/>
<!-- 单点登录阀门 -->
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
</Host>
</Engine>
</Service>
</Server>
3.2 web.xml - 全局应用配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 默认 MIME 类型映射 -->
<mime-mapping>
<extension>json</extension>
<mime-type>application/json</mime-type>
</mime-mapping>
<!-- 欢迎文件列表 -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.do</welcome-file>
</welcome-file-list>
<!-- 会话超时配置(分钟) -->
<session-config>
<session-timeout>30</session-timeout>
<cookie-config>
<http-only>true</http-only>
<secure>true</secure>
</cookie-config>
</session-config>
<!-- 错误页面配置 -->
<error-page>
<error-code>404</error-code>
<location>/error/404.html</location>
</error-page>
<!-- 过滤器配置 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
3.3 context.xml - 上下文配置
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!-- 会话管理器 -->
<Manager className="org.apache.catalina.session.PersistentManager">
<Store className="org.apache.catalina.session.FileStore"
directory="session-data"/>
</Manager>
<!-- 数据库连接池 -->
<Resource name="jdbc/MyDB"
auth="Container"
type="javax.sql.DataSource"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC"
username="dbuser"
password="dbpass"
maxTotal="100"
maxIdle="30"
maxWaitMillis="10000"
validationQuery="SELECT 1"
testOnBorrow="true"
testWhileIdle="true"
timeBetweenEvictionRunsMillis="30000"
minEvictableIdleTimeMillis="60000"/>
<!-- 环境变量 -->
<Environment name="app.config.path"
value="/opt/config"
type="java.lang.String"
override="false"/>
<!-- JNDI 配置 -->
<ResourceLink name="linkToGlobalResource"
global="UserDatabase"
type="org.apache.catalina.UserDatabase"/>
</Context>
3.4 日志配置
3.4.1 logging.properties
# 日志级别
handlers = 1catalina.org.apache.juli.FileHandler, \
2localhost.org.apache.juli.FileHandler, \
3manager.org.apache.juli.FileHandler, \
java.util.logging.ConsoleHandler
# 控制台输出
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = org.apache.juli.OneLineFormatter
# Catalina 日志
1catalina.org.apache.juli.FileHandler.level = INFO
1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
1catalina.org.apache.juli.FileHandler.prefix = catalina.
1catalina.org.apache.juli.FileHandler.encoding = UTF-8
# 访问日志
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = \
2localhost.org.apache.juli.FileHandler
# 包级别日志设置
org.apache.catalina.level = INFO
org.apache.coyote.level = INFO
3.4.2 访问日志格式
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="localhost_access_log"
suffix=".txt"
pattern="combined"
fileDateFormat="yyyy-MM-dd"
rotatable="true"
maxDays="90">
可用 pattern 格式:
- common:
%h %l %u %t "%r" %s %b - combined:
%h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" - 自定义:
%{X-Forwarded-For}i %l %u %t "%r" %s %b %D
四、Tomcat 集群部署
4.1 集群架构
负载均衡器 (Nginx/Apache)
|
┌───┴───┐
│ │
Tomcat1 Tomcat2 (多个节点)
│ │
└───┬───┘
|
共享会话存储
(Redis/Memcached/数据库)
4.2 集群配置
4.2.1 server.xml 集群配置
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="8">
<!-- 管理器 -->
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
<!-- 通道 -->
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<!-- 成员服务 -->
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>
<!-- 接收器 -->
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto"
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
<!-- 发送器 -->
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<!-- 拦截器 -->
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>
</Channel>
<!-- 阀门 -->
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt"/>
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>
<!-- 集群监听器 -->
<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
4.2.2 web.xml 集群配置
<!-- 在应用的 web.xml 中添加 -->
<distributable/>
<!-- 或使用注解方式 -->
<!-- 在 Servlet 类上添加 @DistributionConfig -->
4.3 负载均衡配置
4.3.1 Nginx 配置
upstream tomcat_cluster {
# 负载均衡策略
# least_conn; # 最少连接
# ip_hash; # IP 哈希(会话保持)
hash $request_uri consistent; # URL 哈希
# 服务器列表
server 192.168.1.101:8080 weight=3 max_fails=3 fail_timeout=30s;
server 192.168.1.102:8080 weight=2 max_fails=3 fail_timeout=30s;
server 192.168.1.103:8080 weight=1 max_fails=3 fail_timeout=30s backup;
# 健康检查
keepalive 32;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://tomcat_cluster;
# 反向代理配置
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 连接超时
proxy_connect_timeout 30s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# 缓冲
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
# WebSocket 支持
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# 健康检查端点
location /health {
access_log off;
return 200 "healthy\n";
}
}
4.3.2 Apache HTTPD + mod_jk
# httpd.conf 或 apache2.conf
LoadModule jk_module modules/mod_jk.so
# workers.properties
worker.list=loadbalancer
worker.tomcat1.type=ajp13
worker.tomcat1.host=192.168.1.101
worker.tomcat1.port=8009
worker.tomcat1.lbfactor=1
worker.tomcat1.socket_keepalive=true
worker.tomcat2.type=ajp13
worker.tomcat2.host=192.168.1.102
worker.tomcat2.port=8009
worker.tomcat2.lbfactor=2
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=tomcat1,tomcat2
worker.loadbalancer.sticky_session=true
worker.loadbalancer.sticky_session_force=true
4.4 会话保持策略
4.4.1 Tomcat 内置集群会话复制
<!-- 使用 DeltaManager(全量复制) -->
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"
stateTransferTimeout="60"/>
4.4.2 Redis 集中式会话存储
- 添加依赖(pom.xml):
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.6.0</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-redis-session-manager</artifactId>
<version>2.0.0</version>
</dependency>
- 配置 context.xml:
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
host="redis://127.0.0.1:6379"
port="6379"
database="0"
password=""
maxInactiveInterval="1800"
sessionPersistPolicies="SAVE_ON_CHANGE"
sentinelMaster="mymaster"
sentinels="127.0.0.1:26379,127.0.0.2:26379"/>
4.4.3 Memcached 会话存储
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:192.168.1.101:11211,n2:192.168.1.102:11211"
sticky="false"
sessionBackupAsync="false"
lockingMode="auto"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"/>
五、性能优化配置
5.1 JVM 优化
# catalina.sh 或 setenv.sh
export JAVA_OPTS="-server \
-Xms4096m \
-Xmx4096m \
-XX:MetaspaceSize=256m \
-XX:MaxMetaspaceSize=512m \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:ParallelGCThreads=4 \
-XX:ConcGCThreads=2 \
-XX:InitiatingHeapOccupancyPercent=70 \
-XX:+DisableExplicitGC \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/opt/tomcat/logs/heapdump.hprof \
-Djava.net.preferIPv4Stack=true \
-Dfile.encoding=UTF-8"
5.2 连接器优化
<Connector port="8080"
protocol="org.apache.coyote.http11.Http11Nio2Protocol"
maxThreads="1000"
minSpareThreads="100"
maxConnections="10000"
connectionTimeout="20000"
keepAliveTimeout="15000"
maxKeepAliveRequests="100"
acceptCount="500"
acceptorThreadCount="2"
processorCache="2000"
tcpNoDelay="true"
socketBuffer="8192"
enableLookups="false"
compression="on"
compressionMinSize="2048"
useSendfile="true"
server="Unknown">
</Connector>
5.3 数据库连接池优化
<Resource name="jdbc/MyDB"
type="javax.sql.DataSource"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mydb"
username="user"
password="pass"
# 连接池配置
maxTotal="100"
maxIdle="30"
minIdle="10"
initialSize="10"
# 连接验证
validationQuery="SELECT 1"
testOnBorrow="true"
testWhileIdle="true"
testOnReturn="false"
# 空闲连接处理
timeBetweenEvictionRunsMillis="30000"
minEvictableIdleTimeMillis="60000"
numTestsPerEvictionRun="3"
# 连接等待
maxWaitMillis="10000"
# 预防连接泄漏
removeAbandoned="true"
removeAbandonedTimeout="60"
logAbandoned="true"/>
5.4 监控与诊断
5.4.1 JMX 监控
# 启用 JMX 远程监控
export CATALINA_OPTS="-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=9010 \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.authenticate=false \
-Djava.rmi.server.hostname=服务器IP"
5.4.2 使用 VisualVM 或 JConsole 监控
# 添加 JMX 参数
-Djava.rmi.server.hostname=localhost
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9090
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
六、安全配置
6.1 SSL/TLS 配置
# 生成密钥库
keytool -genkeypair \
-alias tomcat \
-keyalg RSA \
-keysize 2048 \
-keystore /opt/tomcat/conf/keystore.jks \
-validity 3650 \
-storepass changeit \
-keypass changeit \
-dname "CN=example.com, OU=IT, O=Company, L=City, ST=State, C=CN"
# 导出证书
keytool -exportcert \
-alias tomcat \
-keystore /opt/tomcat/conf/keystore.jks \
-file /opt/tomcat/conf/tomcat.crt \
-storepass changeit
<!-- server.xml SSL 配置 -->
<Connector port="8443"
protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150"
SSLEnabled="true"
scheme="https"
secure="true"
clientAuth="false"
sslProtocol="TLS"
sslEnabledProtocols="TLSv1.2,TLSv1.3"
ciphers="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384">
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/keystore.jks"
certificateKeystorePassword="changeit"
certificateKeystoreType="JKS"
type="RSA" />
</SSLHostConfig>
</Connector>
6.2 安全加固措施
<!-- 1. 禁用不必要的方法 -->
<security-constraint>
<web-resource-collection>
<web-resource-name>Restricted Methods</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
<http-method>TRACE</http-method>
</web-resource-collection>
<auth-constraint/>
</security-constraint>
<!-- 2. 隐藏版本信息 -->
<Context>
<Valve className="org.apache.catalina.valves.ErrorReportValve"
showReport="false"
showServerInfo="false"/>
</Context>
<!-- 3. 限制文件列表 -->
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
七、实用脚本
7.1 启动/停止脚本
#!/bin/bash
# tomcat-manager.sh
TOMCAT_HOME="/opt/tomcat"
JAVA_HOME="/usr/lib/jvm/java-11-openjdk"
PID_FILE="$TOMCAT_HOME/temp/tomcat.pid"
case "$1" in
start)
if [ -f "$PID_FILE" ]; then
echo "Tomcat is already running"
exit 1
fi
echo "Starting Tomcat..."
export JAVA_HOME=$JAVA_HOME
$TOMCAT_HOME/bin/startup.sh
;;
stop)
if [ ! -f "$PID_FILE" ]; then
echo "Tomcat is not running"
exit 1
fi
echo "Stopping Tomcat..."
$TOMCAT_HOME/bin/shutdown.sh -force
sleep 10
if [ -f "$PID_FILE" ]; then
kill -9 $(cat $PID_FILE)
rm -f $PID_FILE
fi
;;
restart)
$0 stop
sleep 5
$0 start
;;
status)
if [ -f "$PID_FILE" ]; then
PID=$(cat $PID_FILE)
if ps -p $PID > /dev/null; then
echo "Tomcat is running (PID: $PID)"
else
echo "Tomcat is not running (stale PID file)"
rm -f $PID_FILE
fi
else
echo "Tomcat is not running"
fi
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
;;
esac
7.2 日志清理脚本
#!/bin/bash
# clean-tomcat-logs.sh
TOMCAT_HOME="/opt/tomcat"
LOG_DIR="$TOMCAT_HOME/logs"
DAYS_TO_KEEP=30
# 清理旧日志
find $LOG_DIR -name "*.log" -mtime +$DAYS_TO_KEEP -delete
find $LOG_DIR -name "*.txt" -mtime +$DAYS_TO_KEEP -delete
find $LOG_DIR -name "*.out" -mtime +7 -delete
# 清空 catalina.out(保留最近内容)
if [ -f "$LOG_DIR/catalina.out" ]; then
tail -n 1000 $LOG_DIR/catalina.out > $LOG_DIR/catalina.out.tmp
mv $LOG_DIR/catalina.out.tmp $LOG_DIR/catalina.out
fi
echo "Log cleanup completed at $(date)"
八、故障排除
8.1 常见问题及解决方案
8.1.1 内存泄漏
# 1. 检查内存使用
jmap -heap <pid>
jstat -gc <pid> 1000 10
# 2. 生成堆转储
jmap -dump:live,format=b,file=heapdump.hprof <pid>
# 3. 分析工具
# - Eclipse MAT
# - VisualVM
# - JProfiler
8.1.2 线程阻塞
# 1. 查看线程栈
jstack <pid> > thread_dump.txt
# 2. 查找死锁
jstack <pid> | grep -A 10 "deadlock"
# 3. 监控线程状态
top -H -p <pid>
8.1.3 连接池问题
-- 检查数据库连接
SHOW PROCESSLIST;
-- 查看连接状态
SHOW STATUS LIKE 'Threads_connected';
8.2 监控指标
# 1. 检查当前连接数
netstat -an | grep :8080 | wc -l
# 2. 监控系统资源
vmstat 1 10
iostat -x 1 10
# 3. 查看 Tomcat 状态
curl http://localhost:8080/manager/status?XML=true
九、最佳实践
- 生产环境配置
- 使用单独的 Tomcat 用户运行
- 禁用 manager 和 host-manager 应用
- 设置适当的文件权限
- 配置日志轮转
- 性能优化
- 使用 NIO/NIO2 连接器
- 调整线程池大小
- 启用压缩
- 使用 sendfile 特性
- 高可用性
- 实现会话共享
- 配置健康检查
- 设置适当的超时时间
- 实现故障转移
- 安全性
- 定期更新 Tomcat 版本
- 配置 SSL/TLS
- 限制管理访问
- 禁用不必要的方法
- 监控维护
- 设置日志监控
- 配置告警机制
- 定期备份配置
- 性能基准测试
这份笔记涵盖了 Tomcat 的主要方面,可以根据具体需求进一步深入各个主题。建议在生产环境中进行充分的测试和验证。
Comments NOTHING