linux中级_Tomcat

TJCcc 发布于 2026-01-25 19 次阅读


一、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 规范WebSocketJDK 要求
10.x5.03.04.02.0JDK 11+
9.x4.02.33.01.1JDK 8+
8.x3.12.33.01.1JDK 7+
7.x3.02.22.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 &quot;%r&quot; %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&amp;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 集中式会话存储

  1. 添加依赖(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>
  1. 配置 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

九、最佳实践

  1. 生产环境配置
  • 使用单独的 Tomcat 用户运行
  • 禁用 manager 和 host-manager 应用
  • 设置适当的文件权限
  • 配置日志轮转
  1. 性能优化
  • 使用 NIO/NIO2 连接器
  • 调整线程池大小
  • 启用压缩
  • 使用 sendfile 特性
  1. 高可用性
  • 实现会话共享
  • 配置健康检查
  • 设置适当的超时时间
  • 实现故障转移
  1. 安全性
  • 定期更新 Tomcat 版本
  • 配置 SSL/TLS
  • 限制管理访问
  • 禁用不必要的方法
  1. 监控维护
  • 设置日志监控
  • 配置告警机制
  • 定期备份配置
  • 性能基准测试

这份笔记涵盖了 Tomcat 的主要方面,可以根据具体需求进一步深入各个主题。建议在生产环境中进行充分的测试和验证。

唯有极致沉淀,才能造就辉煌。
最后更新于 2026-01-25