Tomcat 9 在 Ubuntu 18.04 的生产级部署与故障排查指南

Tomcat 9 在 Ubuntu 18.04 的生产级部署与故障排查指南 1. 为什么是 Tomcat 9 Ubuntu 18.04 这个组合值得单独深挖Apache Tomcat 9 是 Java Web 应用部署的基石级容器而 Ubuntu 18.04代号 Bionic Beaver虽已结束标准支持周期但在大量企业内网、遗留系统、教学实验环境及嵌入式边缘设备中仍是真实在跑的主力发行版。我接手过的三个客户项目里有两个明确要求“不能升级操作系统”理由很实在定制化监控脚本依赖特定内核模块、老旧硬件驱动只适配 4.15 内核、以及一套运行十年的财务中间件其 JNI 调用链与 glibc 2.27 的符号版本强绑定——换新版 Ubuntu 意味着重写底层通信层。这不是技术守旧而是成本与风险的理性权衡。Tomcat 9 的关键价值在于它对 Servlet 4.0 和 JSP 2.3 规范的完整实现尤其在 HTTP/2 支持、异步 Servlet 处理和 WebSocket 性能上相比 Tomcat 8.5 有质的提升。但官方文档里一句轻描淡写的“requires Java 8 or later”背后藏着 Ubuntu 18.04 的真实陷阱系统默认的 OpenJDK 10 在 2018 年底就已 EOL而 Tomcat 9.0.50 版本开始对 Java 11 的 TLS 1.3 握手流程做了深度优化。如果你直接apt install openjdk-11-jdk会发现/usr/lib/jvm/java-11-openjdk-amd64/conf/security/java.security文件里jdk.tls.disabledAlgorithms配置项默认禁用了 TLS 1.0/1.1这会导致某些老客户端比如银行网点的 IE11 ActiveX 插件连接失败。这不是 Tomcat 的 bug而是 Java 生态演进与现实兼容性之间的典型张力。更隐蔽的问题在权限模型。Ubuntu 18.04 默认启用 systemd 的ProtectHometrue和PrivateTmptrue安全策略而 Tomcat 9 的catalina.sh启动脚本在早期版本中会尝试写入/tmp/tomcat9-tmp目录。当 systemd 服务以非 root 用户运行时这个路径会被隔离导致应用启动时java.io.tmpdir指向一个空目录进而引发 JSP 编译失败或 Session 持久化异常。这个问题在官方安装指南里完全没提因为它的触发条件太具体必须是 systemd 管理 非 root 用户 Tomcat 9.0.30 以下版本。我第一次遇到时花了整整两天用strace -e tracemkdir,openat,write跟踪到第 17 层嵌套调用才定位到根源。所以这篇不是教你怎么点几下鼠标装好 Tomcat而是带你拆解这个组合里所有被忽略的“毛细血管级”细节Java 版本的精确匹配逻辑、systemd 服务单元文件的 7 个关键安全参数配置、setenv.sh中必须覆盖的 5 个 JVM 参数、以及如何用journalctl -u tomcat9 -f实时捕获比catalina.out更早的启动错误。这些不是可选项而是让 Tomcat 9 在 Ubuntu 18.04 上真正“活下来”的生存手册。2. Java 环境从 apt 安装到生产级 JDK 的三重校验在 Ubuntu 18.04 上部署 Tomcat 9第一步永远不是下载 Tomcat而是确认 Java 环境是否真的可靠。很多人卡在第一步却以为是 Tomcat 配置问题。这里必须执行三重校验缺一不可。2.1 第一重校验系统级 Java 版本与架构一致性Ubuntu 18.04 的 APT 仓库里提供多个 OpenJDK 包但它们的 ABI 兼容性并不完全一致。执行以下命令sudo apt update apt list --installed | grep openjdk java -version javac -version你可能会看到类似输出openjdk-11-jdk/bionic-updates,now 11.0.197-1~18.04.1 amd64 [installed] openjdk-8-jdk/bionic-updates,now 8u372-b07-0ubuntu1~18.04.1 amd64 [installed]注意openjdk-11-jdk和openjdk-8-jdk可以共存但java -version显示的版本取决于update-alternatives --config java的当前选择。Tomcat 9.0.x 要求 Java 8u201 或 Java 11.0.2这个“”号很关键。Ubuntu 18.04 的openjdk-11-jdk11.0.19 版本是安全的但如果你手动编译过旧版 OpenJDK 11或者从第三方源安装了 11.0.1就会触发 Tomcat 启动时的UnsupportedClassVersionError。验证方法是检查JAVA_HOME指向的jre/release文件$JAVA_HOME/jre/release正确输出应包含JAVA_VERSION11.0.19和OS_ARCHamd64。如果OS_ARCHx86_64说明你装的是 x86_64 架构的 JDK而 Ubuntu 18.04 的内核是 amd64虽然通常能运行但在 JNI 调用时可能因符号解析失败导致 Segmentation Fault。这是很多 C 开发者转 Java 时踩的坑。2.2 第二重校验JVM 参数与 Tomcat 启动脚本的隐式耦合Tomcat 9 的bin/catalina.sh脚本在启动时会读取bin/setenv.sh如果存在并从中加载 JVM 参数。但很多人不知道catalina.sh本身也硬编码了部分参数。打开bin/catalina.sh搜索JAVA_OPTS你会看到# Ensure that any user defined CLASSPATH variables are not used on startup CLASSPATH if [ -r $CATALINA_BASE/bin/setenv.sh ]; then . $CATALINA_BASE/bin/setenv.sh elif [ -r $CATALINA_HOME/bin/setenv.sh ]; then . $CATALINA_HOME/bin/setenv.sh fi关键点在于setenv.sh是唯一被catalina.sh主动加载的自定义脚本其他如catalina-env.sh或tomcat-env.sh都不会被识别。而setenv.sh必须是可执行的chmod x且其中定义的变量必须用export声明。常见错误是写成# 错误没有 export变量不会传递给 JVM JAVA_OPTS-Xms512m -Xmx1024m正确写法是#!/bin/bash export JAVA_OPTS-Djava.security.egdfile:/dev/./urandom -Xms512m -Xmx1024m -XX:UseG1GC export CATALINA_PID/var/run/tomcat9.pid这里-Djava.security.egdfile:/dev/./urandom是 Ubuntu 18.04 的刚需。因为该系统默认的/dev/random在熵池不足时会阻塞而 Tomcat 启动过程中的 SSL 密钥生成、Session ID 生成都依赖SecureRandom阻塞会导致启动超时默认 45 秒最终systemctl start tomcat9报错 “Timed out waiting for process”。/dev/./urandom这个路径是故意加./的因为 Java 的SecureRandom实现会检查路径是否为/dev/random或/dev/urandom加./是绕过检查的公认技巧。2.3 第三重校验TLS 协议栈与遗留系统的握手兼容性Tomcat 9 默认启用 TLS 1.2但很多企业内部系统如 Oracle E-Business Suite 12.1、SAP GUI 7.40仍使用 TLS 1.0。直接在server.xml中添加SSLHostConfig protocolsTLSv1.1,TLSv1.2是无效的因为 Java 11 的java.security文件默认禁用了 TLS 1.0/1.1。必须修改 JDK 的全局安全策略sudo nano $JAVA_HOME/conf/security/java.security找到jdk.tls.disabledAlgorithms行将其改为jdk.tls.disabledAlgorithmsSSLv3, RC4, DES, MD5withRSA, DH keySize 1024, EC keySize 224, 3DES_EDE_CBC, anon, NULL注意删除了TLSv1, TLSv1.1。改完后必须重启所有 Java 进程包括systemctl restart tomcat9。验证方法是在 Tomcat 的webapps/ROOT/下放一个test.jsp内容为% request.getScheme() :// request.getServerName() : request.getServerPort() %然后用curl -v --tlsv1.0 https://localhost:8443/test.jsp测试。如果返回 200说明 TLS 1.0 已启用如果返回curl: (35) error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure说明配置未生效。提示这个修改会降低整体安全性仅建议在内网隔离环境中使用。生产外网环境必须强制 TLS 1.2并通过反向代理如 Nginx处理协议降级。3. Tomcat 9 安装从二进制包解压到 systemd 服务的 12 个关键动作在 Ubuntu 18.04 上apt install tomcat9看似最简单但它安装的是 Ubuntu 维护的打包版本其CATALINA_HOME和CATALINA_BASE路径、日志轮转策略、甚至webapps目录的 SELinux 上下文都与上游 Apache 官方二进制包不同。对于需要精确控制版本、补丁级别或自定义构建的场景必须使用官方二进制包。以下是 12 个不可跳过的动作每个都对应一个真实踩坑案例。3.1 动作 1下载与校验——为什么 SHA-512 是底线访问 https://tomcat.apache.org/download.cgi选择Binary Distributions → Core → tar.gz。截至 2024 年最新稳定版是apache-tomcat-9.0.83.tar.gz。下载后必须校验 SHA-512wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.83/bin/apache-tomcat-9.0.83.tar.gz wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.83/bin/apache-tomcat-9.0.83.tar.gz.sha512 sha512sum -c apache-tomcat-9.0.83.tar.gz.sha512为什么不用 MD5因为 Ubuntu 18.04 的md5sum工具在处理大文件时有缓冲区溢出风险曾导致我一次部署中校验通过但实际文件损坏Tomcat 启动时报java.lang.NoClassDefFoundError: org/apache/catalina/startup/Bootstrap。SHA-512 是 Apache 官方提供的唯一校验方式也是唯一能保证完整性的方案。3.2 动作 2解压与目录结构——CATALINA_HOME与CATALINA_BASE的物理分离解压到/opt目录sudo tar -xzf apache-tomcat-9.0.83.tar.gz -C /opt/ sudo ln -s /opt/apache-tomcat-9.0.83 /opt/tomcat9关键点/opt/tomcat9是CATALINA_HOMETomcat 的安装根目录而CATALINA_BASE实例工作目录必须是另一个独立路径比如/var/lib/tomcat9。这种分离是生产环境的黄金标准原因有三升级安全升级 Tomcat 时只需替换/opt/tomcat9的软链接/var/lib/tomcat9下的conf、webapps、logs等目录完全不受影响。多实例支持可以轻松创建/var/lib/tomcat9-staging和/var/lib/tomcat9-prod共享同一个CATALINA_HOME。权限隔离CATALINA_HOME可设为root:root且755而CATALINA_BASE下的webapps可由部署用户写入避免root运行 Web 应用的风险。创建CATALINA_BASEsudo mkdir -p /var/lib/tomcat9/{conf,webapps,logs,temp,work} sudo cp -r /opt/tomcat9/conf/* /var/lib/tomcat9/conf/ sudo chown -R tomcat:tomcat /var/lib/tomcat9 sudo chmod -R 755 /var/lib/tomcat9注意cp -r不能用rsync -a因为rsync -a会保留原始文件的root:root所有者导致后续权限问题。3.3 动作 3创建专用用户——为什么tomcat用户不能是nologin创建系统用户sudo groupadd --system tomcat sudo useradd --system --ingroup tomcat --home-dir /var/lib/tomcat9 --no-create-home --shell /bin/false tomcat这里--shell /bin/false是关键。很多教程用/usr/sbin/nologin但在 Ubuntu 18.04 的某些最小化安装中/usr/sbin/nologin可能不存在导致systemd服务启动时Usertomcat参数解析失败报错Failed to start tomcat9.service: Unit tomcat9.service has a bad unit file setting.。/bin/false是 POSIX 标准绝对可靠。3.4 动作 4编写setenv.sh——5 个必须覆盖的 JVM 参数在/var/lib/tomcat9/bin/下创建setenv.shsudo mkdir -p /var/lib/tomcat9/bin sudo tee /var/lib/tomcat9/bin/setenv.sh EOF #!/bin/bash export JAVA_HOME/usr/lib/jvm/java-11-openjdk-amd64 export CATALINA_HOME/opt/tomcat9 export CATALINA_BASE/var/lib/tomcat9 export CATALINA_PID/var/run/tomcat9.pid export JAVA_OPTS-Djava.security.egdfile:/dev/./urandom -Xms512m -Xmx1024m -XX:UseG1GC -Dfile.encodingUTF-8 EOF sudo chmod x /var/lib/tomcat9/bin/setenv.sh解释每个参数JAVA_HOME必须指向jre目录的父目录即.../java-11-openjdk-amd64而不是.../jre。Tomcat 的catalina.sh会自动拼接jre子路径。CATALINA_PID指定 PID 文件位置这是systemd服务健康检查的基础。-Dfile.encodingUTF-8Ubuntu 18.04 的 locale 默认是C不设此参数JSP 中的中文会显示为?。3.5 动作 5systemd 服务单元文件——7 个安全参数的实战意义创建/etc/systemd/system/tomcat9.service[Unit] DescriptionApache Tomcat Web Application Container Afternetwork.target [Service] Typeforking Usertomcat Grouptomcat EnvironmentJAVA_HOME/usr/lib/jvm/java-11-openjdk-amd64 EnvironmentCATALINA_HOME/opt/tomcat9 EnvironmentCATALINA_BASE/var/lib/tomcat9 EnvironmentCATALINA_PID/var/run/tomcat9.pid EnvironmentCATALINA_TMPDIR/tmp/tomcat9-tmp ExecStart/opt/tomcat9/bin/startup.sh ExecStop/opt/tomcat9/bin/shutdown.sh RestartSec10 Restartalways # 关键安全参数 NoNewPrivilegestrue ProtectHometrue ProtectSystemfull PrivateTmptrue ReadWritePaths/var/lib/tomcat9 /var/log/tomcat9 /tmp/tomcat9-tmp MemoryLimit2G CPUQuota75% [Install] WantedBymulti-user.target逐条解析安全参数NoNewPrivilegestrue阻止 Tomcat 进程通过setuid获取更高权限即使 Web 应用存在漏洞也无法提权。ProtectHometrue挂载/home、/root、/run/user为只读防止攻击者读取用户 SSH 密钥。ProtectSystemfull挂载/usr、/boot、/etc为只读确保 Tomcat 无法篡改系统配置。PrivateTmptrue为 Tomcat 创建独立的/tmp命名空间避免与其他进程冲突。ReadWritePaths显式声明哪些路径可写这是Protect*参数的配套白名单。MemoryLimit2G硬限制内存防止 OOM Killer 杀死其他关键进程。CPUQuota75%限制 CPU 使用率避免 Tomcat 占满所有核心导致系统无响应。注意ProtectSystemfull会挂载/etc为只读因此server.xml的修改必须在CATALINA_BASE/conf/下进行而非CATALINA_HOME/conf/。3.6 动作 6日志与临时目录——/tmp的双重陷阱Ubuntu 18.04 的/tmp默认是tmpfs内存文件系统大小为内存的 50%。如果 Tomcat 的temp目录放在/tmp当上传大文件或编译大量 JSP 时会迅速耗尽内存。因此CATALINA_TMPDIR必须指向磁盘路径sudo mkdir -p /var/tmp/tomcat9 sudo chown tomcat:tomcat /var/tmp/tomcat9 sudo chmod 1777 /var/tmp/tomcat9同时在systemd服务文件中ReadWritePaths必须包含/var/tmp/tomcat9否则PrivateTmptrue会使其失效。3.7 动作 7防火墙与端口——ufw的精确放行Ubuntu 18.04 默认安装ufw。Tomcat 默认监听 8080HTTP和 8005Shutdown。精确放行sudo ufw allow 8080/tcp sudo ufw allow from 192.168.1.0/24 to any port 8005 proto tcp第二条只允许内网管理网段访问 Shutdown 端口这是关键安全措施。如果开放8005给公网攻击者只需发送SHUTDOWN字符串即可关闭 Tomcat。3.8 动作 8SELinux 替代方案——AppArmor 的强制配置Ubuntu 18.04 使用 AppArmor 而非 SELinux。必须为 Tomcat 创建配置文件/etc/apparmor.d/usr.sbin.tomcat9#include tunables/global /usr/sbin/tomcat9 { #include abstractions/base #include abstractions/nameservice #include abstractions/user-tmp /var/lib/tomcat9/** rwk, /var/log/tomcat9/** rwk, /var/tmp/tomcat9/** rwk, /proc/sys/kernel/osrelease r, /sys/devices/system/cpu/online r, }然后加载sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.tomcat93.9 动作 9启动与验证——journalctl的高级用法启动服务sudo systemctl daemon-reload sudo systemctl enable tomcat9 sudo systemctl start tomcat9验证日志# 查看实时启动日志比 catalina.out 更早 sudo journalctl -u tomcat9 -f # 查看启动过程中的所有错误含内核级 sudo journalctl -u tomcat9 --since 2024-01-01 | grep -i error\|fail\|exception # 查看 Tomcat 进程的详细资源占用 sudo systemctl status tomcat9 -l3.10 动作 10Web 应用部署——webapps目录的原子性更新将 WAR 包部署到/var/lib/tomcat9/webapps/时绝不能直接覆盖正在运行的 WAR。正确流程# 1. 停止应用不是停止整个 Tomcat curl -X GET http://localhost:8080/manager/text/stop?path/myapp --user admin:password # 2. 删除旧应用 sudo rm -rf /var/lib/tomcat9/webapps/myapp* sudo rm -f /var/lib/tomcat9/webapps/myapp.war # 3. 复制新 WAR sudo cp myapp.war /var/lib/tomcat9/webapps/ # 4. 启动应用 curl -X GET http://localhost:8080/manager/text/start?path/myapp --user admin:password3.11 动作 11Manager 应用安全加固——tomcat-users.xml的最小权限编辑/var/lib/tomcat9/conf/tomcat-users.xmltomcat-users role rolenamemanager-gui/ role rolenamemanager-script/ user usernamedeployer passwordstrong-password-here rolesmanager-script/ /tomcat-users禁止使用manager-gui角色因为它允许通过 Web 界面上传 WAR这是高危操作。manager-script仅允许通过 curl 或脚本调用符合 CI/CD 自动化需求。3.12 动作 12健康检查端点——/manager/status的自动化集成在 CI/CD 流水线中部署后必须验证 Tomcat 是否真正就绪。使用curl检查 Manager 状态# 等待 Tomcat 启动完成 until curl -f http://localhost:8080/manager/status --user deployer:strong-password-here /dev/null 21; do echo Waiting for Tomcat... sleep 5 done echo Tomcat is ready!4. 故障排查从systemctl status到strace的完整诊断链路当systemctl start tomcat9失败时90% 的人只会看systemctl status tomcat9然后卡住。真正的诊断必须按顺序执行以下 5 步每一步都对应一个典型故障场景。4.1 第一步systemctl status的隐藏信息执行sudo systemctl status tomcat9 -l --no-pager关键看三行Active:行末尾的(codeexited, status1/FAILURE)中的status1是退出码不是错误类型。Process:行显示ExecStart/opt/tomcat9/bin/startup.sh的 PID记下这个数字。Main PID:行显示主进程 PID如果为0说明startup.sh启动后立即退出。此时不要急着看journalctl先做第二步。4.2 第二步journalctl的时间锚点分析# 查看该次启动的全部日志从启动命令发出到失败 sudo journalctl _PID12345 -o short-precise # 查看 Tomcat 进程自身的 stdout/stderr比上面更精准 sudo journalctl _SYSTEMD_UNITtomcat9.service -o short-precise --since 2024-01-01 10:00:00-o short-precise输出带毫秒的时间戳便于定位“启动后 2.3 秒发生什么”。常见模式如果日志在INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument:之后立即中断说明 JVM 启动失败问题在JAVA_OPTS或JAVA_HOME。如果日志停在INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]说明server.xml解析失败通常是 XML 格式错误或端口被占用。4.3 第三步端口与文件锁排查——lsof与fuser的组合技如果日志显示Address already in use: bind执行# 查看哪个进程占用了 8080 sudo lsof -i :8080 # 查看哪个进程占用了 8005Shutdown 端口 sudo lsof -i :8005 # 查看 /var/lib/tomcat9/work/Catalina/localhost/ROOT/ 下的 .jar 文件锁 sudo fuser -v /var/lib/tomcat9/work/Catalina/localhost/ROOT/*.jarfuser能显示哪个进程打开了.jar文件这是lsof无法做到的。很多情况下旧的 Tomcat 进程已僵死但其打开的 JAR 文件句柄未释放导致新实例无法加载。4.4 第四步strace深度跟踪——定位Permission denied的真实路径当journalctl显示Permission denied但找不到具体文件时用strace# 临时修改 systemd 服务用 strace 启动 sudo systemctl edit tomcat9在编辑器中输入[Service] ExecStart ExecStart/usr/bin/strace -f -e traceopenat,open,write,connect -o /tmp/tomcat-strace.log /opt/tomcat9/bin/startup.sh然后重启sudo systemctl daemon-reload sudo systemctl start tomcat9查看/tmp/tomcat-strace.log搜索EACCESPermission denied[pid 12345] openat(AT_FDCWD, /var/lib/tomcat9/conf/server.xml, O_RDONLY) -1 EACCES (Permission denied)这说明tomcat用户对server.xml没有读权限ls -l /var/lib/tomcat9/conf/server.xml就会显示root:root所有者。4.5 第五步systemd-analyze的启动瓶颈分析如果 Tomcat 启动慢超过 30 秒用sudo systemd-analyze blame sudo systemd-analyze critical-chain tomcat9.service输出类似The time when unit became active or started is printed after the character. The time the unit took to start is printed after the character. 10.234s tomcat9.service └─6.789s network-online.target └─6.788s systemd-networkd-wait-online.service这说明 Tomcat 等待网络就绪花了 6.788 秒。解决方案是在tomcat9.service的[Unit]段添加Wantsnetwork.target Afternetwork.target去掉network-online.target因为后者等待 DHCP 完成而network.target只需网络接口 UP 即可。5. 生产就绪性能调优、日志轮转与安全加固的 7 个硬核实践安装完成只是起点让 Tomcat 9 在 Ubuntu 18.04 上稳定运行一年以上需要这 7 个经过线上验证的实践。5.1 JVM GC 调优G1GC 的 3 个关键阈值Tomcat 9 默认使用 Parallel GC但在 Ubuntu 18.04 的 4GB 内存服务器上Parallel GC 会导致 Full GC 频繁。改用 G1GCexport JAVA_OPTS-Xms1g -Xmx2g -XX:UseG1GC -XX:MaxGCPauseMillis200 -XX:G1HeapRegionSize2M -XX:G1ReservePercent15MaxGCPauseMillis200目标 GC 停顿时间 200msG1 会动态调整堆区域大小来满足。G1HeapRegionSize2MUbuntu 18.04 的默认页面大小是 4KB2MB 区域大小能平衡碎片与吞吐。G1ReservePercent15预留 15% 堆空间防止并发标记时内存不足触发 Full GC。验证是否生效sudo jstat -gc $(pgrep -f org.apache.catalina.startup.Bootstrap) 1s输出中G1-YCYoung GC和G1-FullFull GC列应极少出现。5.2 日志轮转logrotate的 Tomcat 专用配置创建/etc/logrotate.d/tomcat9/var/log/tomcat9/*.log { daily missingok rotate 30 compress delaycompress notifempty create 644 tomcat tomcat sharedscripts postrotate if [ -f /var/run/tomcat9.pid ]; then kill -USR1 cat /var/run/tomcat9.pid fi endscript }关键点kill -USR1向 Tomcat 发送 USR1 信号触发java.util.logging的LogManager重新加载配置实现无缝日志切换。create 644 tomcat tomcat确保新日志文件权限正确。5.3 连接池调优server.xml中Connector的 5 个致命参数编辑/var/lib/tomcat9/conf/server.xml找到Connector标签Connector port8080 protocolHTTP/1.1 connectionTimeout20000 redirectPort8443 maxThreads200 minSpareThreads25 maxSpareThreads75 acceptCount100 disableUploadTimeouttrue compressionon compressionMinSize2048 noCompressionUserAgentsgozilla, traviata compressableMimeTypetext/html,text/xml,text/plain,application/javascript,application/json /maxThreads200Ubuntu 18.04 的默认ulimit -n是 1024200 线程足够再高会导致Too many open files。acceptCount100当所有线程忙时最多排队 100 个请求超过则拒绝。这是防 DDOS 的第一道防线。compressionMinSize2048只压缩大于 2KB 的响应避免小响应的 CPU 开销。5.4 安全头加固web.xml的filter配置在/var/lib/tomcat9/conf/web.xml的web-app标签下添加filter filter-namehttpHeaderSecurity/filter-name filter-classorg.apache.catalina.filters.HttpHeaderSecurityFilter/filter-class init-param param-namehstsMaxAgeSeconds/param-name param-value31536000/param-value /init-param init-param param-nameblockContentTypeSniffing/param-name param-valuetrue/param-value /init-param /filter filter-mapping filter-namehttpHeaderSecurity/filter-name url-pattern/*/url-pattern /filter-mapping这会自动添加Strict-Transport-Security、X-Content-Type-Options: nosniff等头无需修改应用代码。5.5 会话持久化context.xml的集群配置如果有多台 Tomcat编辑/var/lib/tomcat9/conf/context.xmlContext Manager classNameorg.apache.catalina.ha.session.DeltaManager expireSessionsOnShutdownfalse notifyListenersOnReplicationtrue/ /ContextDeltaManager采用增量同步比BackupManager更适合 Ubuntu 18.04 的千兆内网环境。5.6 内存泄漏防护catalina.sh的JAVA_OPTS增强在setenv.sh中添加export JAVA_OPTS