Tomcat 完整使用教程

目录

  1. Tomcat 简介
  2. 安装与配置
  3. 目录结构
  4. 内存配置
  5. 部署应用
  6. 配置详解
  7. 性能优化
  8. HTTPS 配置
  9. 常见问题与解决
  10. 监控与管理
  11. Windows 服务管理
  12. 附录:完整 setenv.bat 模板

1. Tomcat 简介

Apache Tomcat 是 Apache 软件基金会旗下的开源 Java Web 服务器,用于运行 Java Servlet、JSP 和 JavaWebSocket 应用。

graph LR A[客户端请求] --> B[Tomcat Connector] B --> C[Container 容器] C --> D[Servlet 处理] D --> E[响应返回] E --> A

核心组件

组件 作用
Server Tomcat 最顶层容器,代表整个服务器
Service 包含 Connector 和 Container
Connector 负责处理网络连接
Container 负责处理 Servlet/JSP

2. 安装与配置

2.1 下载安装

  1. 访问 Tomcat 官网
  2. 下载 Windows Installer 或压缩包(推荐)
  3. 解压到指定目录

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 为什么需要配置内存

flowchart LR A[Java 应用] -->|创建对象| B[堆内存 Heap] A -->|加载类信息| C[Metaspace 元空间] B -->|满了| D[GC 垃圾回收] D -->|回收失败| E[OOM 内存溢出]

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.batcatalina.batcall setenv.batcatalina.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=128JvmMx=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_OPTSJAVA_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 部署方式

graph TD A[部署方式] --> B[WAR 包部署] A --> C[解压 WAR 包] A --> D[IDE 直接运行] B --> E[放入 webapps 目录] C --> F[直接解压到 webapps] E --> G[Tomcat 自动解压]

5.2 WAR 包部署

方式一:拷贝 WAR 文件

myapp.war 拷贝到 webapps/ 目录,Tomcat 会自动解压部署。

方式二:使用 Tomcat Manager

  1. 配置用户权限(在 conf/tomcat-users.xml 中):
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<user username="admin" password="123456" roles="manager-gui,manager-script"/>
  1. 访问 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 线程池优化

graph LR A[请求] --> B[Connector 线程池] B -->|有空闲线程| C[处理请求] B -->|无空闲线程| D[加入等待队列] D -->|队列满| E[拒绝请求] C --> F[返回响应]

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)

flowchart TD A[内存溢出] --> B[Heap Space] A --> C[Metaspace] A --> D[GC Overhead Limit] A --> E[Unable to create native thread] B --> F[增加 -Xmx] C --> G[增加 -XX:MaxMetaspaceSize] D --> H[检查内存泄漏] E --> I[减少 -Xss 或 -Xmx]

解决步骤:

  1. 添加堆转储参数:
set CATALINA_OPTS=-Xms4g -Xmx16g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\tomcat\logs
  1. 重启 Tomcat,复现问题
  2. 使用 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 服务

flowchart LR A[手动启动] --> B[需要用户登录] A --> C[关闭窗口会停止] A --> D[开机不自启] E[Windows 服务] --> F[开机自动启动] E --> G[后台运行] E --> H[无需用户登录] E --> I[可统一管理]

11.2 安装 Tomcat 为服务

前置条件

  1. 确保以管理员身份运行命令提示符
  2. 确保 JDK/JRE 已正确安装并配置 JAVA_HOME 环境变量
  3. 确保 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 多实例服务管理

flowchart TD A[多 Tomcat 实例] --> B[不同端口] A --> C[不同内存配置] A --> D[不同应用] B --> E[Tomcat1 : 8080] B --> F[Tomcat2 : 8081] B --> G[Tomcat3 : 8082]

安装多个 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

服务状态显示「正在运行」但无法访问

flowchart TD A[服务运行中但无法访问] --> B[检查端口是否冲突] B --> C[netstat -ano &#124; findstr 8080] A --> D[检查防火墙] D --> E[允许 8080 端口] A --> F[检查应用是否部署成功] F --> G[查看 logs 目录日志] G --> H[检查 catalina.out]

服务与命令行启动差异

对比项 命令行启动 服务启动
启动用户 当前用户 SYSTEM
环境变量 从当前 shell 继承 从注册表读取
工作目录 当前目录 Tomcat bin 目录
setenv.bat 会加载 不加载(procrun 不走 catalina.bat)
控制台输出 直接显示 写入 logs/tomcat8-stdout.*.log
JVM 参数来源 setenv.batCATALINA_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 指定了服务进程的启动方式和管理模式,是配置服务最关键的参数之一。

flowchart TD A[systemd Service Type] --> B[simple] A --> C[forking] A --> D[oneshot] A --> E[notify] A --> F[dbus] A --> G[idle]

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.shsystemctl restart
参数存储位置 注册表 环境变量 / shell 脚本
是否需要重新安装服务 改参数不需要重装,但需要 //US// 更新 不需要,改完重启即可

附录:完整 setenv.bat 模板

posted @ 2026-06-01 10:59  RK5123153  阅读(15)  评论(0)    收藏  举报