ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Tomcat 8.5.85安装部署实战:JDK配置、参数调优与排错指南

Tomcat 8.5.85安装部署实战:JDK配置、参数调优与排错指南 简介这是Apache Tomcat 8.5.85版本的安装包zip压缩约10.63MB共619个文件。面向需要在Windows或Linux环境部署Java Web应用的开发与运维人员适合快速搭建符合Servlet与JSP规范的动态Web项目运行环境。该版本支持Java EE 7规范具备Servlet容器、JSP渲染、会话管理、连接池及基础安全管理等能力也便于教学演示、接口调试及版本固定的离线生产部署。包内含226个html页面、98个class编译类、72个java源文件、57个jsp动态页面、34个jar依赖库、17个xml配置、多个bat/sh启停脚本与properties配置文件等主要类型覆盖服务启动、运行依赖、页面展示和参数调试多个方面。目录沿用bin、conf、lib、webapps、logs等标准结构解压后即可对照定位启动脚本、服务配置、应用放置和日志输出减少盲目摸索。已有733人浏览学习。资源版本明确、文件完整可离线反复安装使用通过配置CATALINA_HOME环境变量即可启动服务将WAR包放入webapps实现自动部署。默认提供manager管理入口的权限配置说明和server.xml关键参数调整思路可帮助读者快速完成Tomcat安装、目录识别、应用发布和基础排错适合从入门到日常运维使用。1. Tomcat 8.5.85为什么值得专门找一个安装包Tomcat 8.5 系列已经走到生命周期的末尾而 8.5.85 恰好是这一个系列的收官版本。很多还在维护老项目的团队Java 环境停留在 Java SE 8Spring 版本也锁死在 5.x 甚至更早这时候升级到 Tomcat 9 或 10 不是技术问题是兼容性风险问题。与其冒险升大版本不如找一个稳定的 8.5.x 收官版把生产环境钉死。8.5.85 修复了大量在 8.5.54 之前存在的连接器、会话管理和 WebSocket 相关的问题同时保持了和 Java SE 8 的完整兼容是目前老技术栈里性价比最高的选择之一。标题里的安装包三个字其实是另一个关键信息很多人第一次接触 Tomcat 就是靠集成环境或镜像一键拉起的根本没手动装过。但生产环境、内网环境、老旧服务器上你经常面对的是一个不能联网、没有 Docker、连 yum 源都配不全的裸机器。这时候手里有一个完整的 Tomcat 8.5.85 安装包自己解压、配 JDK、调参数、起服务整套流程走一遍比任何自动化脚本都可靠。这篇文章不做科普只讲落地。我会按实际部署的顺序讲清楚 8.5.85 的目录结构、JDK 环境怎么配、服务怎么拉起、参数怎么调、哪些坑一定绕不开。新手跟着做能跑通老手也能在参数和排查部分找到能直接用的东西。2. 认识 Tomcat 8.5.85版本定位、目录结构与安装包选型2.1 8.5.x 和 9.0.x 的分水岭在哪里Tomcat 8.5 是一个特殊的存在。它表面上跟 9.0 共享了大部分代码基础但实际上它是从 8.0 直接跳跃过来的跳过了 Servlet 4.0 的完整实现只保留了 Servlet 3.1 的规范同时引入了 9.0 里的 NIO 连接器作为默认。这意味着 8.5.85 在并发处理能力上跟 9.0 差距不大但 API 层面完全兼容老项目。对大多数还在用 Spring 4、Spring 5 的老项目来说9.0 和 8.5 在字节码层面的差异根本感知不到但 8.5 的兼容性更稳。很多老项目的web.xml里有奇怪的配置或者依赖某些只在 Servlet 3.1 下才正常工作的过滤器升到 9.0 直接启动失败换回 8.5.85 就一切正常。这不是玄学是规范版本差异造成的。2.2 安装包的两种形态ZIP 分发包与 Windows 服务版Tomcat 官方发布的 8.5.85 安装包分两种形态Windows Service Installerexe 安装器和 ZIP 压缩包。我的建议是不管你是 Windows 还是 Linux一律用 ZIP 包。原因有三点。第一exe 安装器会把 Tomcat 注册成 Windows 服务这本身不是坏事但安装器默认的服务参数里堆了一堆不需要的配置出了问题不好排查。ZIP 包完全可控服务怎么启、环境变量怎么配全在你手里。第二ZIP 包在 Linux 和 Windows 上通用同一个压缩包解压就能用批量部署的时候只需要改配置文件。第三exe 安装器在部分精简版 Windows Server 上会因为缺少系统组件而安装失败ZIP 包不存在这个限制。2.3 Tomcat 8.5.85 目录结构哪些目录能删哪些目录千万别动ZIP 包解压之后你会看到一个标准的目录树。我先按生产环境的要求给你过一遍同时标出哪些是敏感目录。apache-tomcat-8.5.85/ ├── bin/ # 启动与关闭脚本Linux 用 .shWindows 用 .bat ├── conf/ # 核心配置文件server.xml、web.xml、context.xml 都在这里 ├── lib/ # Tomcat 自身及共享的 Java 类库别乱放 jar ├── logs/ # 运行日志目录catalina.out、localhost.log 都在这里 ├── temp/ # 临时文件目录重启会自动清理 ├── webapps/ # 应用部署目录war 包扔这里自动解压 ├── work/ # JSP 编译后的 class 文件缓存目录 ├── LICENSE # 许可证文件 ├── NOTICE # 版权声明 └── RELEASE-NOTES # 版本说明里面记录了此版本修复的问题conf和logs是最重要的两个目录。conf不用多说Tomcat 的所有行为都由它控制logs是你排错时最先看的地方。work目录可以删Tomcat 启动时会自动重建temp目录也可以清空但要注意正在运行的时候别去删否则正在写入的临时文件会出问题。webapps目录下默认有一堆自带应用比如 docs、examples、manager生产环境建议全删掉只留 ROOT。2.4 ROOT 应用与自带管理台装完第一步该做什么解压完成后直接启动 Tomcat访问 8080 端口你会看到一个默认欢迎页。这个欢迎页由webapps/ROOT提供。生产环境中这个 ROOT 目录一般会被替换成你的项目产物比如把构建出来的静态资源直接丢进 ROOT或者用 war 包名字来访问应用。webapps/manager是 Tomcat 的管理控制台默认只有本机能访问而且需要在conf/tomcat-users.xml里配置用户才能登录。如果你不需要远程管理应用建议把webapps/manager和webapps/host-manager整个删除。这两个目录是爆破攻击的高频目标删掉一了百了。2.5 安装包来源与校验MD5、SHA512 与官方校验值下载安装包时注意核对官方发布的 SHA512 校验值。Tomcat 官方发布页面会随压缩包一起给出对应的校验值文件如.sha512下载后执行如下校验# 在压缩包所在目录执行 sha512sum apache-tomcat-8.5.85.tar.gz # 将输出结果与 .sha512 文件里的值对比 cat apache-tomcat-8.5.85.tar.gz.sha512参数说明sha512sum是 Linux 自带的校验工具Windows 下可以用 PowerShell 的Get-FileHash -Algorithm SHA512替代。如果校验值对不上说明文件被篡改或下载不完整直接弃用。这个步骤在无法访问官方源、只能从镜像站下载的场景下尤其重要。3. 环境准备与安装从 JDK 到启动脚本的最小可行配置3.1 JDK 版本选型Java SE 8 还是 11Tomcat 8.5.85 官方要求的 JDK 版本下限是 Java SE 7但要稳定运行生产环境最低也得是 Java SE 8。如果用 Java SE 11 运行 Tomcat 8.5.85 也能工作因为 Tomcat 8.5 在后期版本中增加了对 Java SE 11 的支持但这不是最优解。我的经验是老项目用 Java SE 8选 8u202 或更高的最后一个免费版本新项目不要用 Tomcat 8.5直接用 Tomcat 9 或 10 对应新版 JDK。这个判断依据是Tomcat 8.5 的很多优化路径还是针对 Java SE 8 的逃逸分析和 G1 回收器调参思路换到 Java SE 11 上收益不大反而可能因为模块化权限问题多出额外的配置步骤。3.2 配置 JAVA_HOMEWindows 和 Linux 两套标准写法安装 Tomcat 之前必须先确认 Java 环境变量。Tomcat 的启动脚本完全依赖JAVA_HOME或JRE_HOME来定位 Java 运行时没有配置这个变量启动脚本直接报Cannot find JAVA_HOME并退出。Linux 环境下的配置写在/etc/profile或当前用户的~/.bashrc里export JAVA_HOME/usr/local/java/jdk1.8.0_202 export PATH$JAVA_HOME/bin:$PATH export CATALINA_HOME/opt/apache-tomcat-8.5.85 export PATH$CATALINA_HOME/bin:$PATH参数说明JAVA_HOME指向 JDK 解压后的根目录不是bin目录。CATALINA_HOME指向 Tomcat 解压后的根目录。配置完成后执行source /etc/profile让配置生效然后运行java -version验证 Java 是否可用运行echo $CATALINA_HOME验证路径是否已写入。Windows 环境下在系统属性里新建JAVA_HOME环境变量值为 JDK 根目录比如C:\Program Files\Java\jdk1.8.0_202。然后在 Path 变量里追加%JAVA_HOME%\bin。注意不要在 Path 里写死完整路径否则以后换 JDK 版本还得改 Path。3.3 Linux 下启动 Tomcatstartup.sh 与 catalina.sh 的区别Linux 系统下启动 Tomcat 有两种常见方式直接执行startup.sh或使用catalina.sh run。两者差别很大新手经常在这上面翻车。startup.sh是后台启动方式脚本执行完立刻返回 shell 控制权Tomcat 在后台运行。好处是不占用当前终端坏处是刚启动时看不到日志输出出错时只能事后去看logs/catalina.out。catalina.sh run是前台运行方式Tomcat 进程不会脱离终端所有日志直接打到当前控制台按Ctrl C就能停掉服务。这个模式最适合第一次启动排查问题。# 切换到 Tomcat 的 bin 目录 cd /opt/apache-tomcat-8.5.85/bin # 给脚本加执行权限如果之前没有 chmod x *.sh # 前台方式启动适合看完整启动日志 ./catalina.sh run参数说明第一次启动推荐用catalina.sh run因为你能直接看到日志实时打出来发现问题可以马上按CtrlC终止然后修改配置重启。确认无报错后以后正常启动用./startup.sh即可。如果catalina.sh run启动正常但startup.sh启动后访问不了端口多半是环境变量没传递到后台进程检查CATALINA_HOME是否为绝对路径。3.4 Windows 下启动 Tomcatstartup.bat 与窗口关闭的误解Windows 环境下启动 Tomcat 直接双击bin/startup.bat会弹出一个命令行窗口。很多人关掉这个窗口后发现 Tomcat 也停了以为 Tomcat 不支持后台运行这是个经典误解。startup.bat本身启动的是一个前台进程窗口关闭时操作系统会向进程发送终止信号。要让 Tomcat 在 Windows 上真正后台运行有两个方案一是用bin/tomcat8w.exe如果安装包带 Windows 服务安装器把 Tomcat 注册成系统服务二是用javaw配合catalina.bat的start参数。常见做法是用系统服务方式因为这样开机自启、异常重启都是系统级别管理的比手动脚本稳定很多。3.5 启动后的标准验证端口、进程、日志三层检查无论哪种方式启动验证服务是否正常不要只看没报错要做三层检查第一层检查端口监听状态。Tomcat 默认监听 8080 端口用netstat -tlnp | grep 8080Linux或netstat -ano | findstr 8080Windows确认端口在监听。如果端口没监听说明 Tomcat 进程没有正常拉起或启动到一半崩了。第二层检查进程状态。Linux 下ps aux | grep tomcatWindows 下tasklist | findstr java。这里要注意 Tomcat 的进程名显示为java不是tomcat。第三层检查日志结尾。查看logs/catalina.outLinux或logs/catalina.日期.logWindows看到Server startup in [xxx] milliseconds这一行才算真正启动成功。4. 配置核心参数让 Tomcat 8.5.85 在软硬件上都跑得稳4.1 server.xml 里必调的三个参数conf/server.xml是 Tomcat 最核心的配置文件连接器、端口、虚拟主机全在这里。生产环境里这个文件里的默认配置根本不够用至少需要调整三个参数。第一个是连接器端口和协议。默认配置是 HTTP/1.1 协议8080 端口这个能跑但并发上来之后吞吐量不行。建议显式指定protocolorg.apache.coyote.http11.Http11NioProtocolNIO 模型在线程占用和并发处理上比原来的 BIO 强得多Tomcat 8.5 虽然默认已经是 NIO但显式写出来方便别人一眼看明白。第二个是maxThreads。默认值是 200对很多内部系统够用但如果你做了压测发现响应时间在某个并发量之后突然恶化优先考虑调大这个值。一般初始配置 400之后根据压测结果和服务器 CPU 核数调整。注意这个值不是越大越好线程太多时上下文切换开销会吃掉 CPU。第三个是connectionTimeout。默认 20000 毫秒对公网服务有点长对内部服务又有点短。这个参数要结合你的业务场景改公网服务建议降到 5000内部服务保持 20000 或调高到 30000。Connector port8080 protocolorg.apache.coyote.http11.Http11NioProtocol maxThreads400 acceptCount300 connectionTimeout20000 redirectPort8443 /参数说明acceptCount是等待队列长度当所有线程都在忙时新的请求会进这个队列排队默认 100可以适当调大到 300。redirectPort是 HTTPS 重定向端口如果你没配 HTTPS 也没打算配保持默认即可。改动 server.xml 后必须重启 Tomcat 才生效。4.2 JVM 内存参数catalina.sh 里怎么改才不出错Tomcat 默认的 JVM 堆内存是物理内存的 1/4对很多部署机来说这个值不够用。改 JVM 参数的正确位置在bin/catalina.shLinux或bin/catalina.batWindows的顶部区域通过设置CATALINA_OPTS环境变量来实现。常见做法是在 catalina.sh 中找到# OS specific support之前的区域添加如下配置JAVA_OPTS-Djava.awt.headlesstrue -Dfile.encodingUTF-8 -server \ -Xms1024m -Xmx2048m -XX:NewSize256m -XX:MaxNewSize384m \ -XX:PermSize256m -XX:MaxPermSize512m参数说明-Xms1024m指定 JVM 启动时分配的初始堆内存-Xmx2048m指定最大堆内存。-Xms和-Xmx建议设置成相同值避免运行期 JVM 不断扩展堆内存带来的性能抖动。-XX:PermSize和-XX:MaxPermSize只对 Java SE 8 及以前版本有效如果你用的是 Java SE 11这两个参数直接不能用会启动失败Java SE 11 需要用-XX:MetaspaceSize替代。另外注意内存参数是根据你部署机器的物理内存来定的如果服务器只有 4GB 内存-Xmx2048m已经是上限再调大可能引发操作系统内存不足触发 OOM Killer。4.3 日志配置catalina.out 无限增长的解决办法Tomcat 默认会把所有控制台输出写到logs/catalina.out这个文件不会自动分割时间久了能涨到几个 GB。磁盘满是最常被忽略的运维事故解决办法是让系统工具来做日志轮转。Linux 环境下使用 logrotate 配置轮转规则# 在 /etc/logrotate.d/ 下新建 tomcat 文件 /opt/apache-tomcat-8.5.85/logs/catalina.out { daily rotate 7 copytruncate compress missingok notifempty dateext }参数说明daily表示每天轮转一次rotate 7保留最近 7 份日志copytruncate是先复制日志文件内容再清空原文件这样 Tomcat 不需要重启就能完成轮转compress对轮转出的旧日志做 gzip 压缩节省磁盘空间dateext让轮转出的日志文件名带上日期后缀。4.4 应用部署war 包放 webapps 里就能跑但要注意解压行为部署应用最直接的方式是把 war 包复制到webapps目录下Tomcat 检测到新 war 包后会自动解压并部署。这个行为在真实环境中有一个很大的坑如果你直接覆盖同名 war 包Tomcat 在某些版本下不会重新解压还是加载旧代码。# 部署新版本的 war 包 cp app-demo.war /opt/apache-tomcat-8.5.85/webapps/ # 停掉 Tomcat 再清理旧残留保证干净部署 /opt/apache-tomcat-8.5.85/bin/shutdown.sh rm -rf /opt/apache-tomcat-8.5.85/webapps/app-demo rm -rf /opt/apache-tomcat-8.5.85/work/Catalina/localhost/app-demo cp app-demo.war /opt/apache-tomcat-8.5.85/webapps/ /opt/apache-tomcat-8.5.85/bin/startup.sh参数说明work/Catalina/localhost/app-demo是 JSP 编译缓存目录这个目录里的旧 class 如果没有清理部署新代码后会出现页面和实际代码不一致的情况。先停 Tomcat、再删残留、再覆盖 war、最后启动这套流程可以保证代码一定是新的。5. 部署后的排错指南端口、权限、乱码、内存的常见坑5.1 端口被占用导致启动失败现象执行startup.sh后终端没有输出错误但访问 8080 端口失败查看catalina.out发现报错Address already in use: JVM_Bind。原因8080 端口已被其他进程占用。可能是另一个 Tomcat 实例在运行也可能是你部署的其他应用占用了这个端口。Tomcat 启动时绑定端口失败会直接终止启动流程但因为 logs 在后台模式不是实时的所以很多人找不到原因。解决先找占用端口的进程。Linux 下执行netstat -tlnp | grep 8080拿到 PID再用ps -ef | grep PID查看是什么程序。如果是另一个 Tomcat执行它的shutdown.sh把旧实例停掉。如果是业务程序确认它是否可以换端口否则需要改 Tomcat 的server.xml端口。改完后再次尝试启动。5.2 启动日志出现严重警告但服务能访问现象Tomcat 能正常启动应用也能访问但catalina.out里刷出The valid characters are defined in RFC 7230 and RFC 3986之类的警告某些接口报 400 错误。原因这是 Tomcat 8.5 对 URL 参数做严格校验导致的。新规范要求 URL 中的字符必须符合 RFC 3986 标准如果你的请求里带有花括号{}、竖线|或中文参数且未做 URL 编码就会被判定为非法请求。解决这个警告的根源是你项目代码里用浏览器地址栏直接拼参数引起的。从根本上应该修正代码对参数做 URL 编码。如果项目太老改不动可以通过server.xml的连接器属性放宽校验改relaxedQueryChars参数把需要放行的字符加进去。5.3 Linux 下启动脚本执行报权限不足现象执行./startup.sh报Permission denied或者提示cannot create directoryTomcat 目录下的文件属于某个用户但当前用户无法写入。原因这是 Linux 文件权限问题不是 Tomcat 本身的问题。用tar解压的压缩包默认权限不一定包含可执行位而且如果 Tomcat 目录属于 root 用户你用普通用户启动时会因为写不了logs和work目录而报错。解决给当前用户授权 Tomcat 目录的写权限。常见做法是把 Tomcat 目录属主改成用当前用户执行chown -R 用户名:组名 /opt/apache-tomcat-8.5.85然后执行chmod x bin/*.sh给脚本加执行权限。生产环境里不建议用 root 直接跑 Tomcat单独建一个tomcat用户来跑服务是更安全的选择。5.4 JSP 页面中文乱码现象部署的应用页面上所有中文都显示为问号或乱码但代码文件本身在本地 Intellij IDEA 里看是正常的。原因Tomcat 8.5.85 默认的 URI 编码和响应编码是 UTF-8但 JSP 文件的保存编码、页面声明的编码、Tomcat 连接器的 URI 编码三者不一致。典型场景是代码文件是 GBK 保存的而项目里所有页面声明charsetUTF-8直接导致运行时双重转码出错。解决先确认代码文件本身的编码格式与该格式一致地修改 JSP 页面头部的contentType声明。同时在server.xml的连接器上加URIEncodingUTF-8参数显式指定请求参数的解码方式。last 一种兜底方案是在每个 JSP 头部加% page languagejava contentTypetext/html; charsetUTF-8 pageEncodingUTF-8 %但根因还是代码文件编码与页面声明要一致。5.5 应用频繁 Full GC响应时间偶尔飙升现象应用整体运行正常但每隔一段时间会出现一次明显的响应延迟持续几秒后恢复。查看 JVM 监控发现老年代内存占用周期性降下来一次。原因堆内存设置不合理-Xms和-Xmx不一致导致 JVM 在运行期不断扩展堆扩展过程中触发 Full GC。另一种可能是-Xmx设置过小应用的高峰流量把堆打满JVM 不断触发 Full GC 来腾空间。解决按第 4.2 节的方案把-Xms和-Xmx设为相同值数值参考服务器的物理内存。如果问题依旧用jstat -gcutil PID 1000观察 GC 频率和耗时确定是分配过小还是代码有内存泄漏。JVM 参数调整没有一劳永逸的方案需要按监控数据持续调。6. 生产环境最后一道防线把 JVM 参数固化与备份恢复的习惯养成走到这一步Tomcat 已经跑起来了应用也部署上去了。但真正的生产环境考验不是能访问而是重启之后还能不能按预期恢复。我见过太多团队Tomcat 装好之后配置改了无数回但没有人把最终的完整配置沉淀成一份可复用的交付文档。结果半年后服务器扩容新机器上从零开始装又踩一遍所有坑。我的习惯是准备一份DEPLOY.md放在 Tomcat 的根目录外面不放进 Tomcat 目录避免被误删记录当前环境的完整信息包括服务器操作系统版本、JAVA_HOME 路径、JDK 具体版本号、CATALINA_HOME 路径、JVM 参数完整内容、server.xml 里改过哪些自带配置、部署了哪些应用对应端口情况。这份文档不需要长篇大论能让人照着在一台空机器上还原环境就行。另外一个直接有效的方法是备份conf目录。Tomcat 的配置全都在conf下备份这个目录就相当于备份了所有关键设置。每次调完参数确认稳定后执行一次备份# 备份当前稳定的 conf 目录 cp -r /opt/apache-tomcat-8.5.85/conf /opt/tomcat-backup/conf-$(date %F) # 备份 webapps 下已部署的应用 cp -r /opt/apache-tomcat-8.5.85/webapps/app-demo.war /opt/tomcat-backup/这是我屡试不爽的后悔药方案升级某个参数翻车时把备份的conf目录整个拷回去Tomcat 配置瞬间回到稳定态。希望这套排查思路和操作习惯能帮到你让你的 Tomcat 8.5.85 少一些半夜报警多一些平稳运行。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进