Tomcat 完整使用教程
目录
1. Tomcat 简介
Apache Tomcat 是 Apache 软件基金会旗下的开源 Java Web 服务器,用于运行 Java Servlet、JSP 和 JavaWebSocket 应用。
核心组件
| 组件 | 作用 |
|---|---|
| Server | Tomcat 最顶层容器,代表整个服务器 |
| Service | 包含 Connector 和 Container |
| Connector | 负责处理网络连接 |
| Container | 负责处理 Servlet/JSP |
2. 安装与配置
2.1 下载安装
- 访问 Tomcat 官网
- 下载 Windows Installer 或压缩包(推荐)
- 解压到指定目录
2.2 环境变量配置
# 新增系统变量
CATALINA_HOME = D:\apache-tomcat-10.x.x
# 在 PATH 中添加
%CATALINA_HOME%\bin
2.3 验证安装
# 启动 Tomcat
catalina.bat run
# 或使用服务模式
service.bat install
访问 http://localhost:8080 验证是否正常运行。
3. 目录结构
apache-tomcat/
├── bin/ # 启动脚本
│ ├── startup.bat # Windows 启动
│ ├── shutdown.bat # Windows 停止
│ ├── catalina.bat # 核心脚本
│ └── setenv.bat # 环境变量配置(需手动创建)
├── conf/ # 配置文件
│ ├── server.xml # 主配置文件
│ ├── web.xml # 默认 Web 应用配置
│ ├── context.xml # 全局上下文配置
│ └── tomcat-users.xml # 用户认证配置
├── lib/ # 依赖库
├── logs/ # 日志文件
├── temp/ # 临时文件
├── webapps/ # Web 应用部署目录
│ ├── docs/ # Tomcat 文档
│ ├── examples/ # 示例应用
│ └── manager/ # 管理后台
└── work/ # 运行时临时文件(JSP 编译)
4. 内存配置
4.1 为什么需要配置内存
4.2 内存参数说明
| 参数 | 说明 | 推荐值(32GB 内存) |
|---|---|---|
-Xms |
初始堆内存大小 | 4g |
-Xmx |
最大堆内存大小 | 12g - 16g |
-XX:MetaspaceSize |
Metaspace 初始大小 | 512m |
-XX:MaxMetaspaceSize |
Metaspace 最大大小 | 1g |
-Xss |
线程栈大小 | 1m - 2m |
4.3 配置方法
方法一:创建 setenv.bat(推荐)
在 bin/setenv.bat 文件中添加:
:: Windows (bin/setenv.bat)
set CATALINA_OPTS=-Xms4g -Xmx16g -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1g
方法二:直接修改 catalina.bat
在 bin/catalina.bat 文件开头(约第 15 行)添加:
set JAVA_OPTS="-Xms4g -Xmx16g -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1g"
4.4 32GB 内存推荐配置
根据不同使用场景:
# 轻量级应用(只跑 Tomcat + 小应用)
set CATALINA_OPTS=-Xms2g -Xmx4g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m
# 中等应用(常规 Web 应用)
set CATALINA_OPTS=-Xms4g -Xmx12g -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1g
# 大型应用(高并发、微服务)
set CATALINA_OPTS=-Xms8g -Xmx16g -XX:MetaspaceSize=1g -XX:MaxMetaspaceSize=2g
4.5 JVM 参数配置优先级
理解配置优先级至关重要,否则会出现"改了配置但不生效"的问题。
Windows 命令行启动模式(startup.bat)
优先级从高到低:
1. setenv.bat 中的 CATALINA_OPTS(最高)
2. setenv.bat 中的 JAVA_OPTS
3. 系统环境变量 CATALINA_OPTS / JAVA_OPTS
4. catalina.bat 内置默认值(最低)
生效原理: startup.bat → catalina.bat → call setenv.bat,catalina.bat 会主动读取 setenv.bat 中定义的变量。
| 变量 | 用途 | 谁读取 |
|---|---|---|
CATALINA_OPTS |
Tomcat 专用 JVM 参数 | catalina.bat |
JAVA_OPTS |
通用 JVM 参数(其他 Java 程序也会读取) | catalina.bat |
两个变量同时设置时,
CATALINA_OPTS优先级更高。如果只需要给 Tomcat 加参数,用CATALINA_OPTS。
Windows 服务模式(service.bat install)
优先级从高到低:
1. tomcat8.exe //US// 直接写入注册表(最高)
2. service.bat 安装前预设环境变量 JvmMs / JvmMx
3. service.bat 硬编码默认值 JvmMs=128 JvmMx=256(最低)
| 优先级 | 来源 | 说明 |
|---|---|---|
| 1(最高) | 注册表 JvmMs/JvmMx/Options |
通过 tomcat8.exe //US// 直接写入,覆盖一切 |
| 2 | 环境变量 JvmMs/JvmMx |
service.bat install 前手动 set JvmMs=8192,脚本第 165-166 行会检查 |
| 3(最低) | service.bat 第 165-166 行硬编码 |
JvmMs=128、JvmMx=256,写死在脚本中 |
关键结论:setenv.bat 对 Windows 服务模式完全无效。
原因在 service.bat 源码中:
rem service.bat 第 165-166 行(硬编码默认值)
if "%JvmMs%" == "" set JvmMs=128
if "%JvmMx%" == "" set JvmMx=256
rem 第 188-189 行(直接传给 tomcat8.exe,会覆盖 JvmOptions 中的 -Xms/-Xmx)
--JvmMs "%JvmMs%" ^
--JvmMx "%JvmMx%"
service.bat 既不读取 setenv.bat,也不解析 CATALINA_OPTS 或 JAVA_OPTS。而且 --JvmMs/--JvmMx 是独立的注册表键,优先级高于 --JvmOptions 中混入的 -Xms/-Xmx,即使把参数塞进 JvmOptions 也会被这两个写死的值覆盖。
服务模式的正确配置方法:
:: 方法一:安装前设置环境变量(利用脚本第 165-166 行的检查逻辑)
set JvmMs=8192
set JvmMx=8192
service.bat install
:: 方法二:安装后更新注册表(最可靠,推荐)
service.bat install
tomcat8.exe //US//Tomcat8 --JvmMs=8192 --JvmMx=8192
Linux 命令行启动模式(startup.sh)
优先级从高到低:
1. setenv.sh 中的 CATALINA_OPTS(最高)
2. setenv.sh 中的 JAVA_OPTS
3. 系统环境变量 CATALINA_OPTS / JAVA_OPTS
4. catalina.sh 内置默认值(最低)
与 Windows 命令行模式相同,catalina.sh 会主动 source setenv.sh。
Linux systemd 服务模式
优先级从高到低:
1. systemd unit 中的 Environment=(最高)
2. systemd unit 中的 EnvironmentFile=
3. setenv.sh 中的 CATALINA_OPTS / JAVA_OPTS
4. catalina.sh 内置默认值(最低)
与 Windows 服务模式的关键区别: Linux systemd 模式下
setenv.sh可以生效,因为 systemd 本质上还是执行catalina.sh run,脚本链路完整。但如果 systemd unit 中通过Environment=设置了同名变量,会覆盖setenv.sh中的值。
[Service]
# 这个优先级最高,会覆盖 setenv.sh 中的同名变量
Environment="CATALINA_OPTS=-Xms8g -Xmx8g"
# 或者用环境文件
EnvironmentFile=/etc/tomcat/tomcat.conf
ExecStart=/restcloud/tomcat/bin/catalina.sh run
5. 部署应用
5.1 部署方式
5.2 WAR 包部署
方式一:拷贝 WAR 文件
将 myapp.war 拷贝到 webapps/ 目录,Tomcat 会自动解压部署。
方式二:使用 Tomcat Manager
- 配置用户权限(在
conf/tomcat-users.xml中):
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<user username="admin" password="123456" roles="manager-gui,manager-script"/>
- 访问
http://localhost:8080/manager/html
5.3 上下文路径配置
在 conf/server.xml 的 <Host> 节点中添加:
<Context path="/myapp" docBase="D:\myapp" reloadable="true"/>
5.4 热部署配置
在 conf/context.xml 中启用:
<Context reloadable="true">
6. 配置详解
6.1 server.xml 核心配置
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<Service name="Catalina">
<!-- 连接器配置 -->
<Connector port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="500"
minSpareThreads="50"
acceptCount="100"/>
<!-- AJP 连接器(与 Apache/Nginx 配合) -->
<Connector protocol="AJP/1.3"
address="::1"
port="8009"
redirectPort="8443"/>
<!-- 引擎配置 -->
<Engine name="Catalina" defaultHost="localhost">
<!-- 主机配置 -->
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!-- 应用上下文 -->
<Context path="" docBase="ROOT" reloadable="true"/>
</Host>
</Engine>
</Service>
</Server>
6.2 常用配置参数
| 参数 | 说明 | 默认值 |
|---|---|---|
port |
HTTP 端口 | 8080 |
maxThreads |
最大线程数 | 200 |
minSpareThreads |
最小空闲线程 | 10 |
acceptCount |
请求队列长度 | 100 |
connectionTimeout |
连接超时(ms) | 20000 |
enableLookups |
DNS 反查 | false |
6.3 web.xml 配置
路径:conf/web.xml
<!-- session 超时配置(单位:分钟) -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<!-- MIME 类型配置 -->
<mime-mapping>
<extension>html</extension>
<mime-type>text/html</mime-type>
</mime-mapping>
7. 性能优化
7.1 线程池优化
在 server.xml 中优化:
<Connector port="8080"
protocol="HTTP/1.1"
maxThreads="500" <!-- 最大线程数 -->
minSpareThreads="50" <!-- 最小空闲线程 -->
acceptCount="200" <!-- 等待队列长度 -->
compression="on" <!-- 启用压缩 -->
compressionMinSize="2048"
compressibleMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json"/>
7.2 压缩配置
<Connector port="8080"
protocol="HTTP/1.1"
compression="on"
compressionMinSize="1024"
noCompressionUserAgents="gozilla,traviata"
compressibleMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json"/>
7.3 连接器优化
<Connector port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="500"
minSpareThreads="50"
acceptCount="200"
enableLookups="false"
URIEncoding="UTF-8"
compression="on"
keepAliveTimeout="60000"
maxKeepAliveRequests="100"/>
7.4 内存优化建议
# G1 垃圾收集器配置(适合大内存)
set CATALINA_OPTS=-Xms4g -Xmx16g ^
-XX:MetaspaceSize=512m ^
-XX:MaxMetaspaceSize=1g ^
-XX:+UseG1GC ^
-XX:MaxGCPauseMillis=200 ^
-XX:+HeapDumpOnOutOfMemoryError ^
-XX:HeapDumpPath=D:\tomcat\logs\heapdump.hprof
8. HTTPS 配置
8.1 生成密钥库
# 使用 keytool 生成密钥(JDK 内置工具)
keytool -genkey -alias tomcat -keyalg RSA -keystore tomcat.keystore -validity 36500
8.2 配置 HTTPS
在 server.xml 中添加:
<Connector port="8443"
protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150"
SSLEnabled="true"
scheme="https"
secure="true"
keystoreFile="D:\apache-tomcat\conf\tomcat.keystore"
keystorePass="123456"
clientAuth="false"
sslProtocol="TLS"/>
8.3 强制 HTTPS
在 conf/web.xml 末尾添加:
<security-constraint>
<web-resource-collection>
<web-resource-name>HTTPS</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
9. 常见问题与解决
9.1 端口被占用
严重: 无法启动端 口 8080 已被占用
解决方法:
# 查找占用端口的进程
netstat -ano | findstr 8080
# 结束进程(假设 PID 是 1234)
taskkill /PID 1234 /F
# 或修改 server.xml 中的端口
<Connector port="8081" .../>
9.2 内存溢出 (OOM)
解决步骤:
- 添加堆转储参数:
set CATALINA_OPTS=-Xms4g -Xmx16g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\tomcat\logs
- 重启 Tomcat,复现问题
- 使用 MAT 分析堆转储文件
9.3 JSP 页面空白
原因: 可能是 work 目录缓存问题
解决方法:
# 停止 Tomcat
# 清除 work 目录
rm -rf D:\apache-tomcat\work\Catalina\localhost\yourapp
# 重启 Tomcat
9.4 日志乱码
在 conf/logging.properties 中修改:
java.util.logging.ConsoleHandler.encoding = UTF-8
java.util.logging.Handler.encoding = UTF-8
或在 bin/catalina.bat 中添加:
set JAVA_OPTS=%JAVA_OPTS% -Dfile.encoding=UTF-8
9.5 启动缓慢
可能是随机数生成问题,添加:
set CATALINA_OPTS=%CATALINA_OPTS% -Djava.security.egd=file:/dev/./urandom
10. 监控与管理
10.1 使用 JMX 监控
添加 JMX 参数到 setenv.bat:
set CATALINA_OPTS=-Xms4g -Xmx16g ^
-Dcom.sun.management.jmxremote ^
-Dcom.sun.management.jmxremote.port=9999 ^
-Dcom.sun.management.jmxremote.authenticate=false ^
-Dcom.sun.management.jmxremote.ssl=false ^
-Djava.rmi.server.hostname=localhost
10.2 常用管理接口
| 路径 | 说明 |
|---|---|
/manager/status |
服务器状态 |
/manager/html |
Web 管理界面 |
/manager/text |
文本命令接口 |
/host-manager/html |
虚拟主机管理 |
10.3 常用命令
# 启动
catalina.bat start
# 停止
catalina.bat stop
# 前台运行(查看日志)
catalina.bat run
# 以调试模式启动
catalina.bat jpda start
11. Windows 服务管理
11.1 为什么使用 Windows 服务
11.2 安装 Tomcat 为服务
前置条件
- 确保以管理员身份运行命令提示符
- 确保 JDK/JRE 已正确安装并配置
JAVA_HOME环境变量 - 确保
CATALINA_HOME环境变量已配置
方式一:使用 service.bat 安装(推荐)
@echo off
rem 以管理员身份运行
set CATALINA_HOME=D:\apache-tomcat-10.1.x
rem 进入 Tomcat bin 目录
cd /d "%CATALINA_HOME%\bin"
rem 安装服务(使用默认服务名 Tomcat10)
service.bat install
rem 或者指定自定义服务名
service.bat install Tomcat10
验证安装成功:
rem 查看服务列表
sc query Tomcat10
rem 服务应显示:STATE : 4 RUNNING 或 STATE : 1 STOPPED
方式二:手动使用 sc 命令注册服务
@echo off
rem 以管理员身份运行
rem 创建服务
sc create Tomcat10 binPath= "D:\apache-tomcat-10.1.x\bin\tomcat10.exe //RS//Tomcat10"
rem 设置服务描述
sc description Tomcat10 "Apache Tomcat 10.1.x Web Server"
rem 设置服务启动类型为自动
sc config Tomcat10 start= auto
rem 启动服务
net start Tomcat10
方式三:使用 Tomcat10w.exe 可视化工具
Tomcat 提供了一个可视化工具用于管理服务:
@echo off
rem 启动服务配置工具(需要已安装服务)
"D:\apache-tomcat-10.1.x\bin\Tomcat10w.exe" //ES//Tomcat10
rem 最小化到系统托盘模式
"D:\apache-tomcat-10.1.x\bin\Tomcat10w.exe" //MS//Tomcat10
11.3 卸载 Tomcat 服务
方式一:使用 service.bat 卸载
@echo off
rem 以管理员身份运行
set CATALINA_HOME=D:\apache-tomcat-10.1.x
rem 先停止服务(如果正在运行)
net stop Tomcat10
rem 等待服务完全停止
timeout /t 3 /nobreak
rem 卸载服务
"%CATALINA_HOME%\bin\service.bat" remove Tomcat10
方式二:使用 sc 命令卸载
@echo off
rem 以管理员身份运行
rem 停止服务
net stop Tomcat10
rem 强制停止(如果普通停止失败)
taskkill /f /im tomcat10.exe 2>nul
rem 删除服务
sc delete Tomcat10
方式三:完全清理(包括注册表)
如果服务删除后仍有残留:
@echo off
rem 以管理员身份运行
rem 停止并删除服务
net stop Tomcat10 2>nul
sc delete Tomcat10 2>nul
rem 清理注册表(可选)
reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Tomcat\Tomcat10" /f 2>nul
reg delete "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tomcat10" /f 2>nul
11.4 服务管理命令
基础服务命令
# 启动服务
net start Tomcat10
# 停止服务
net stop Tomcat10
# 重启服务
net stop Tomcat10 && net start Tomcat10
# 查看服务状态
sc query Tomcat10
# 查看详细状态(包括 PID)
sc queryex Tomcat10
sc 命令完整管理
@echo off
set SERVICE_NAME=Tomcat10
:: 启动服务
net start %SERVICE_NAME%
:: 停止服务
net stop %SERVICE_NAME%
:: 查看详细状态
sc query %SERVICE_NAME%
sc queryex %SERVICE_NAME%
:: 设置服务为自动启动
sc config %SERVICE_NAME% start= auto
:: 设置服务为手动启动
sc config %SERVICE_NAME% start= demand
:: 禁用服务(开机不启动)
sc config %SERVICE_NAME% start= disabled
服务状态说明
| 状态码 | 状态名 | 说明 |
|---|---|---|
| 1 | STOPPED | 服务已停止 |
| 2 | START_PENDING | 正在启动 |
| 3 | STOP_PENDING | 正在停止 |
| 4 | RUNNING | 服务正在运行 |
| 5 | CONTINUE_PENDING | 正在恢复 |
| 6 | PAUSE_PENDING | 正在暂停 |
| 7 | PAUSED | 已暂停 |
11.5 服务启动参数配置(JVM 参数优先级)
核心结论:setenv.bat 在服务模式下完全无效
Windows 服务启动时走的是 procrun(tomcat8.exe),参数全部来自注册表,与 setenv.bat 无关。
JVM 参数优先级链(服务模式)
优先级从高到低:
1. tomcat8.exe //US// 直接写入注册表(最高)
2. service.bat install 前预设环境变量 JvmMs / JvmMx
3. service.bat 硬编码默认值 JvmMs=128 JvmMx=256(最低)
service.bat 源码中为什么写死 128M/256M
rem service.bat 第 165-166 行
if "%JvmMs%" == "" set JvmMs=128
if "%JvmMx%" == "" set JvmMx=256
rem 第 188-189 行 —— 直接写入 --JvmMs/--JvmMx 注册表键
--JvmMs "%JvmMs%" ^
--JvmMx "%JvmMx%"
--JvmMs/--JvmMx 是独立的注册表键,优先级高于 --JvmOptions 中的 -Xms/-Xmx。即使你把 -Xms8g -Xmx8g 塞进 JvmOptions,也会被 --JvmMs=128 --JvmMx=256 覆盖为 256M。
注册表实际路径
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Apache Software Foundation\Procrun 2.0\<服务名>\Parameters\Java
| 键名 | 类型 | 值示例 | 说明 |
|---|---|---|---|
JvmMs |
REG_DWORD | 0x2000(8192,单位 MB) |
初始堆大小 |
JvmMx |
REG_DWORD | 0x2000(8192,单位 MB) |
最大堆大小 |
Options |
REG_MULTI_SZ | -XX:+UseG1GC;... |
其他 JVM 参数(不含 -Xms/-Xmx) |
注意:
JvmMs/JvmMx的单位是 MB(不是 KB),十六进制值0x2000= 8192 MB = 8 GB。
正确的配置方法
方法一:安装前设置环境变量(利用脚本第 165-166 行的检查逻辑)
管理员 cmd 中执行:
cd /d D:\Apache\Tomcat\apache-tomcat-8.5.37\bin
:: 先设置变量,service.bat 会检查并跳过默认值
set JvmMs=8192
set JvmMx=8192
set JvmArgs=-XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=4 -XX:ConcGCThreads=2 -XX:InitiatingHeapOccupancyPercent=45 -XX:G1ReservePercent=10 -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1g
service.bat remove
service.bat install
net start Tomcat8
方法二:安装后更新注册表(最可靠,推荐)
cd /d D:\Apache\Tomcat\apache-tomcat-8.5.37\bin
service.bat install
:: 更新 JVM 内存参数(单位:MB)
tomcat8.exe //US//Tomcat8 --JvmMs=8192 --JvmMx=8192 ^
--JvmOptions="-Dcatalina.home=D:\Apache\Tomcat\apache-tomcat-8.5.37;-Dcatalina.base=D:\Apache\Tomcat\apache-tomcat-8.5.37;-Djava.io.tmpdir=D:\Apache\Tomcat\apache-tomcat-8.5.37\temp;-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager;-Djava.util.logging.config.file=D:\Apache\Tomcat\apache-tomcat-8.5.37\conf\logging.properties;-XX:+UseG1GC;-XX:MaxGCPauseMillis=200;-XX:ParallelGCThreads=4;-XX:ConcGCThreads=2;-XX:InitiatingHeapOccupancyPercent=45;-XX:G1ReservePercent=10;-XX:MetaspaceSize=512m;-XX:MaxMetaspaceSize=1g"
net start Tomcat8
注意:
--JvmOptions中多个参数用;分隔,路径用/不能用\。
验证配置是否生效
:: 查注册表确认 JvmMx(0x2000 = 8192 MB = 8 GB)
reg query "HKLM\SOFTWARE\WOW6432Node\Apache Software Foundation\Procrun 2.0\Tomcat8\Parameters\Java" /v JvmMx
:: 查看实际运行的 Java 进程参数
wmic process where "name='java.exe'" get commandline
常见配置错误
| 错误做法 | 为什么不行 | 正确做法 |
|---|---|---|
只改 setenv.bat 就重启服务 |
服务不读取 setenv.bat | 用 tomcat8.exe //US// 写注册表 |
把 -Xms -Xmx 写在 --JvmOptions 里 |
--JvmMs/--JvmMx 优先级更高,会覆盖 |
用 --JvmMs=8192 --JvmMx=8192 |
用 reg add 写入错误的注册表路径 |
procrun 的路径不是 Apache Software Foundation\Tomcat |
用 tomcat8.exe //US// 自动写入正确路径 |
在 PowerShell 中执行 service.bat |
PowerShell 不能正确执行 bat 脚本 | 用管理员 cmd 执行 |
11.6 开机自启动配置
方式一:设置服务自动启动
@echo off
rem 以管理员身份运行
sc config Tomcat10 start= auto
方式二:使用任务计划程序
@echo off
rem 创建开机启动任务
schtasks /create /tn "Tomcat10" /tr "D:\apache-tomcat-10.1.x\bin\startup.bat" /sc onlogon /rl limited
rem 删除任务
schtasks /delete /tn "Tomcat10" /f
11.7 多实例服务管理
安装多个 Tomcat 服务:
@echo off
rem 以管理员身份运行
rem 第一个实例
set CATALINA_HOME=D:\apache-tomcat-10.1.x
call "%CATALINA_HOME%\bin\service.bat" install Tomcat1
rem 第二个实例(需要修改 server.xml 端口)
set CATALINA_HOME=D:\apache-tomcat-10.1.x-2
call "%CATALINA_HOME%\bin\service.bat" install Tomcat2
rem 第三个实例
set CATALINA_HOME=D:\apache-tomcat-10.1.x-3
call "%CATALINA_HOME%\bin\service.bat" install Tomcat3
多实例端口冲突解决方案:
修改 conf/server.xml 中的以下端口:
| 端口 | 默认值 | 实例1 | 实例2 | 实例3 |
|---|---|---|---|---|
Connector port |
8080 | 8080 | 8081 | 8082 |
Server port |
8005 | 8005 | 8006 | 8007 |
AJP port |
8009 | 8009 | 8010 | 8011 |
Redirect port |
8443 | 8443 | 8444 | 8445 |
11.8 服务管理批处理脚本
@echo off
setlocal
title Tomcat Service Manager
color 0A
set SERVICE_NAME=Tomcat10
set CATALINA_HOME=D:\apache-tomcat-10.1.x
:menu
cls
echo ========================================
echo Tomcat Windows 服务管理工具
echo ========================================
echo.
echo 1. 启动服务
echo 2. 停止服务
echo 3. 重启服务
echo 4. 查看服务状态
echo 5. 安装服务
echo 6. 卸载服务
echo 7. 设置开机自动启动
echo 8. 设置手动启动
echo 0. 退出
echo.
echo ========================================
set /p choice=请选择操作 [0-8]:
if "%choice%"=="1" goto :start
if "%choice%"=="2" goto :stop
if "%choice%"=="3" goto :restart
if "%choice%"=="4" goto :status
if "%choice%"=="5" goto :install
if "%choice%"=="6" goto :remove
if "%choice%"=="7" goto :auto
if "%choice%"=="8" goto :manual
if "%choice%"=="0" goto :end
echo 无效选择,请重新选择!
timeout /t 2 > nul
goto :menu
:start
echo 正在启动服务 %SERVICE_NAME%...
net start %SERVICE_NAME%
if %errorlevel% EQU 0 (
echo 服务启动成功!
) else (
echo 服务启动失败!
)
pause
goto :menu
:stop
echo 正在停止服务 %SERVICE_NAME%...
net stop %SERVICE_NAME%
if %errorlevel% EQU 0 (
echo 服务停止成功!
) else (
echo 服务停止失败!
)
pause
goto :menu
:restart
echo 正在重启服务 %SERVICE_NAME%...
net stop %SERVICE_NAME% 2>nul
timeout /t 2 > nul
net start %SERVICE_NAME%
if %errorlevel% EQU 0 (
echo 服务重启成功!
) else (
echo 服务启动失败!
)
pause
goto :menu
:status
echo 查询服务状态...
sc query %SERVICE_NAME%
sc queryex %SERVICE_NAME%
pause
goto :menu
:install
echo 正在安装服务...
call "%CATALINA_HOME%\bin\service.bat" install %SERVICE_NAME%
echo 安装完成!
pause
goto :menu
:remove
echo 正在卸载服务...
net stop %SERVICE_NAME% 2>nul
call "%CATALINA_HOME%\bin\service.bat" remove %SERVICE_NAME%
echo 卸载完成!
pause
goto :menu
:auto
echo 设置服务为自动启动...
sc config %SERVICE_NAME% start= auto
echo 设置成功!
pause
goto :menu
:manual
echo 设置服务为手动启动...
sc config %SERVICE_NAME% start= demand
echo 设置成功!
pause
goto :menu
:end
endlocal
exit
11.9 常见服务问题与解决
服务启动失败
@echo off
rem 查看服务日志
sc query %SERVICE_NAME%
sc queryex %SERVICE_NAME%
rem 查看事件日志
eventvwr.msc
服务状态显示「正在运行」但无法访问
服务与命令行启动差异
| 对比项 | 命令行启动 | 服务启动 |
|---|---|---|
| 启动用户 | 当前用户 | SYSTEM |
| 环境变量 | 从当前 shell 继承 | 从注册表读取 |
| 工作目录 | 当前目录 | Tomcat bin 目录 |
| setenv.bat | 会加载 | 不加载(procrun 不走 catalina.bat) |
| 控制台输出 | 直接显示 | 写入 logs/tomcat8-stdout.*.log |
| JVM 参数来源 | setenv.bat → CATALINA_OPTS |
注册表 → JvmMs/JvmMx/Options |
| 修改参数后 | 重启 startup.bat 即可 | 需用 tomcat8.exe //US// 更新注册表后重启服务 |
服务模式无法加载 setenv.bat 的根本原因: Windows 服务通过 procrun(
tomcat8.exe)直接启动 JVM,不经过catalina.bat脚本,因此setenv.bat完全不在调用链路上。所有 JVM 参数必须写入注册表。详见 11.5 节。
12. Linux systemd 服务管理
12.1 systemd Service Type 详解
systemd 的 Type 指定了服务进程的启动方式和管理模式,是配置服务最关键的参数之一。
12.2 各类型详解
Type=simple(推荐用于 Tomcat)
原理: systemd 直接跟踪主进程。如果主进程退出,systemd 立即判定服务失败。
┌─────────────────────────────────┐
│ systemd │
│ │ │
│ └─── catalina.sh run ──→ Java │
│ (直接跟踪,PID=主进程) │
└─────────────────────────────────┘
特点:
- systemd 直接监控主进程 PID
- 服务启动后立即认为成功
- 不需要 PID 文件
- 最稳定的 Tomcat 方案
推荐配置:
[Service]
Type=simple
ExecStart=/restcloud/tomcat/bin/catalina.sh run
ExecStop=/restcloud/tomcat/bin/shutdown.sh
Restart=on-failure
RestartSec=10
Type=forking(传统方式)
原理: systemd 在 ExecStart 进程退出后去读取 PIDFile,根据 PID 跟踪子进程。
┌─────────────────────────────────────┐
│ systemd │
│ │ │
│ ├── startup.sh (父进程) │
│ │ └── catalina.sh │
│ │ └── Java (子进程) │
│ │ ↓ │
│ └── 读取 PIDFile ──→ 跟踪 Java │
└─────────────────────────────────────┘
特点:
- 需要 PIDFile 配置正确
- 父进程退出后 systemd 才跟踪
- 如果 PIDFile 不存在或写入失败,systemd 误判失败
- Tomcat 可能不写 PID 文件(取决于 setenv.sh 的 CATALINA_PID 配置)
问题排查:
# 查看服务状态
systemctl status tomcat
# 查看日志
journalctl -u tomcat -n 50
# 手动检查 PID 文件
cat /restcloud/tomcat/temp/tomcat.pid
# 检查 Java 进程是否实际运行
ps -ef | grep java
配置示例:
[Service]
Type=forking
PIDFile=/restcloud/tomcat/temp/tomcat.pid
ExecStart=/restcloud/tomcat/bin/startup.sh
ExecStop=/restcloud/tomcat/bin/shutdown.sh
Type=oneshot
原理: 服务只执行一次,进程退出后服务状态保持"active (exited)"。
┌─────────────────────────────────┐
│ systemd │
│ │
│ ExecStart: 执行一次 │
│ (进程退出,但服务保持运行) │
│ │
└─────────────────────────────────┘
特点:
- 适用于执行一次就完成的任务(如初始化脚本)
- 服务状态永远是 active,不会失败
- 常用于 oneshot + RemainAfterExit 组合
示例:
[Service]
Type=oneshot
ExecStart=/opt/init.sh
RemainAfterExit=yes
Type=notify
原理: 服务启动完成后发送 sd_notify() 信号,systemd 收到信号后才认为服务启动成功。
┌─────────────────────────────────┐
│ systemd 服务进程 │
│ │ │ │
│ │ startup │
│ │ │ │
│ │ send sd_notify() ───┼──→ READY=1
│ │ │
│ └─── 收到信号 ──→ 标记成功 │
└─────────────────────────────────┘
特点:
- 服务主动通知 systemd 已就绪
- 比 simple 更精确的控制
- 需要服务主动支持 sd_notify
Type=dbus
原理: 服务通过 D-Bus 总线注册自己的名称,systemd 根据 D-Bus 名称的出现来判断服务就绪。
特点:
- 适用于需要 D-Bus 通信的服务
- 桌面环境服务常用
- Tomcat 一般不使用
Type=idle
原理: systemd 延迟执行 ExecStart 直到系统空闲(无其他任务)。
特点:
- 用于避免启动时与其他服务竞争资源
- 很少使用
- Tomcat 不适用
12.3 Tomcat 推荐配置对比
| Type | 适用场景 | 推荐度 | 说明 |
|---|---|---|---|
simple |
生产环境(推荐) | ★★★★★ | 最稳定,不依赖 PID 文件 |
forking |
传统方式 | ★★★☆☆ | 需要正确配置 PIDFile |
notify |
需要精确控制 | ★★☆☆☆ | 需要服务支持 sd_notify |
生产环境推荐 simple 模式:
[Unit]
Description=Tomcat
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=simple
User=root
Group=root
Environment="JAVA_HOME=/usr/jdk"
Environment="CATALINA_HOME=/restcloud/tomcat"
Environment="CATALINA_BASE=/restcloud/tomcat"
ExecStart=/restcloud/tomcat/bin/catalina.sh run
ExecStop=/restcloud/tomcat/bin/shutdown.sh
TimeoutSec=300
# 故障自动重启
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
如果一定要用 forking 模式,必须确保 PIDFile 正确:
[Service]
Type=forking
PIDFile=/restcloud/tomcat/temp/tomcat.pid
Environment="CATALINA_PID=/restcloud/tomcat/temp/tomcat.pid"
ExecStart=/restcloud/tomcat/bin/startup.sh
ExecStop=/restcloud/tomcat/bin/shutdown.sh
12.4 常见问题排查
# 查看服务状态
systemctl status tomcat
# 查看详细日志
journalctl -u tomcat -f
# 重载配置
systemctl daemon-reload
# 完全重启(先kill残留进程)
systemctl stop tomcat
kill -9 $(pgrep -f "org.apache.catalina.startup.Bootstrap") 2>/dev/null
systemctl start tomcat
# 检查进程是否真正运行
ps -ef | grep java | grep tomcat
# 检查端口是否监听
netstat -tlnp | grep 8080
12.5 Linux JVM 参数配置优先级
与 Windows 不同,Linux 下 systemd 服务本质上还是执行 catalina.sh run,脚本链路完整,所以 setenv.sh 可以生效。
优先级链
优先级从高到低:
1. systemd unit 中的 Environment=(最高)
2. systemd unit 中的 EnvironmentFile=
3. setenv.sh 中的 CATALINA_OPTS
4. setenv.sh 中的 JAVA_OPTS
5. 系统环境变量
6. catalina.sh 内置默认值(最低)
各方式说明
| 优先级 | 配置位置 | 示例 | 说明 |
|---|---|---|---|
| 1(最高) | systemd unit Environment= |
Environment="CATALINA_OPTS=-Xms8g -Xmx8g" |
直接写在 service 文件中,覆盖一切 |
| 2 | systemd unit EnvironmentFile= |
EnvironmentFile=/etc/tomcat/tomcat.conf |
从外部文件加载环境变量 |
| 3 | setenv.sh 中的 CATALINA_OPTS |
CATALINA_OPTS="-Xms8g -Xmx8g" |
Tomcat 专用,推荐放在这里 |
| 4 | setenv.sh 中的 JAVA_OPTS |
JAVA_OPTS="-Xms8g -Xmx8g" |
通用 JVM 参数,其他 Java 程序也会读取 |
推荐做法:参数放在 setenv.sh,systemd 只引用
setenv.sh(/restcloud/tomcat/bin/setenv.sh):
CATALINA_OPTS="-Xms8g -Xmx8g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 \
-XX:ParallelGCThreads=4 -XX:ConcGCThreads=2 \
-XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1g \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/restcloud/tomcat/logs/heapdump.hprof \
-XX:+PrintGCDetails -XX:+PrintGCDateStamps \
-Xloggc:/restcloud/tomcat/logs/gc.log \
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M"
systemd unit(/etc/systemd/system/tomcat.service):
[Service]
Type=simple
User=root
Group=root
Environment="JAVA_HOME=/usr/jdk"
Environment="CATALINA_HOME=/restcloud/tomcat"
Environment="CATALINA_BASE=/restcloud/tomcat"
ExecStart=/restcloud/tomcat/bin/catalina.sh run
ExecStop=/restcloud/tomcat/bin/shutdown.sh
TimeoutSec=300
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
验证配置是否生效
# 查看 Java 进程的完整启动参数
ps -ef | grep java | grep tomcat
# 或更清晰地查看堆大小
jinfo -flag MaxHeapSize $(pgrep -f catalina)
# 通过 systemd 查看环境变量
systemctl show tomcat --property=Environment
Linux vs Windows 服务模式关键区别
| 对比项 | Windows 服务 | Linux systemd |
|---|---|---|
| setenv 文件 | 不生效(procrun 走注册表) | 生效(systemd 执行 catalina.sh) |
| 修改参数方式 | tomcat8.exe //US// 写注册表 |
修改 setenv.sh 后 systemctl restart |
| 参数存储位置 | 注册表 | 环境变量 / shell 脚本 |
| 是否需要重新安装服务 | 改参数不需要重装,但需要 //US// 更新 |
不需要,改完重启即可 |

浙公网安备 33010602011771号