4.2 部署方式与目录结构


文档摘要

4.2 部署方式与目录结构 本节摘要:Web 应用是迷宫里的住户,本节讲住户的三种搬家方式——解压目录、WAR 包、管理端远程部署——各自的适用场景与行为差异;逐项解释标准目录树中每个位置的作用;并剖析 autoDeploy 与热部署的触发机制与生产代价。学完你能独立完成一次规范的发布,并知道每种发布方式在日志里长什么样。 4.1 的路由系统认识得再清楚,也得有住户可指。本节补上"应用怎么进来":部署方式的选型、目录结构的约定、以及 autoDeploy 这个默认开启却常被误解的机制——第 7 章排查部署故障时,本节的行为描述就是判据。

4.2 部署方式与目录结构

本节摘要:Web 应用是迷宫里的住户,本节讲住户的三种搬家方式——解压目录、WAR 包、管理端远程部署——各自的适用场景与行为差异;逐项解释标准目录树中每个位置的作用;并剖析 autoDeploy 与热部署的触发机制与生产代价。学完你能独立完成一次规范的发布,并知道每种发布方式在日志里长什么样。

4.1 的路由系统认识得再清楚,也得有住户可指。本节补上"应用怎么进来":部署方式的选型、目录结构的约定、以及 autoDeploy 这个默认开启却常被误解的机制——第 7 章排查部署故障时,本节的行为描述就是判据。

三种搬家方式

方式 操作 适用场景 特点
解压目录 把应用目录直接放进 appBase 开发调试、需要改文件 免打包、改动即时可见
WAR 包 把打包文件放进 appBase 标准发布 原子更新、与构建流水线对接
管理端部署 经 manager 应用上传或脚本触发 远程发布、自动化 不登录机器即可发布

三种方式的共同底层:Tomcat 扫描 appBase 目录(默认 webapps),发现新住户就为它建一个 Context,上下文路径由目录名或包名决定——文件名就是应用的门牌号,这条约定与 4.1 的最长前缀匹配直接挂钩。

认全那棵标准目录树

每个 Web 应用的内部结构由 Servlet 规范约定,一个位置放错,轻则资源读不到,重则应用起不来。

图 4-2:标准目录结构标注图

图 4-2:标准目录结构标注图

用命令把最小应用装配出来,比看图更扎实。六条命令造一个能跑的应用骨架。

# 造一个最小应用 demo 并放进部署目录 base=webapps/demo mkdir -p $base/WEB-INF/classes $base/WEB-INF/lib $base/assets echo '<html>demo home</html>' > $base/index.html cat > $base/WEB-INF/web.xml <<'EOF' <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" version="6.0"> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app> EOF tail -n 4 logs/catalina.out
信息 [ContainerBackgroundProcessor] org.apache.catalina.core.StandardContext[/demo] 部署描述符配置完成 开始处理注解 信息 [main] org.apache.catalina.startup.HostConfig.deployDirectory 把 webapps 中目录 [demo] 的应用部署了 [326] 毫秒

目录放进去几秒内,日志出现部署记录——这就是 autoDeploy 在后台扫描的效果,无需重启。

autoDeploy 与热部署:便利与代价

Host 标签上的 autoDeploy 默认开启,行为是:后台线程周期性扫描 appBase,新目录或新包部署之,更新的包重新部署之,删除的目录卸载之。听起来很美,生产上却要三思。

代价一:内存碎片。反复热部署会让旧应用的类加载器来不及释放,代数累积后出现内存增长,最终要靠定时重启收场——这是"为什么每周要重启一次 Tomcat"的经典答案。代价二:检测有延迟。扫描间隔默认数秒,发布系统若不确认日志就切流量,会有一段新旧混跑。代价三:并发不安全。大包替换瞬间,正巧进来的请求可能撞上半卸载状态。

规范的发布姿势是走管理端或脚本做"停、换、起"的受控流程,用 manager 应用的文本接口一条命令完成。

# 经 manager 的文本接口远程部署一个 WAR 包 curl -u deploy:secret -T target/order-app.war \ 'http://localhost:8080/manager/text/deploy?path=/order&update=true'
OK - Deployed application at context path [/order]

返回 OK 才算发布成功,随后再用 list 接口确认运行状态。这套接口可以嵌进流水线,比"拷文件加祈祷"可靠得多。安全提醒:manager 应用的账号与角色在 5.2 与第 7 章还会出现,弱口令加公网可达的 manager 是经典入侵入口,务必收到内网并强口令。

💡 关键直觉:部署方式的选型其实是"谁负责原子性"——目录直拷没有原子性,WAR 替换有文件级原子性,管理端部署有事务级确认。生产发布至少要到第二档,自动化到位就上第三档。

部署前检查清单与外置目录

发布动作之前过一遍清单,八成的事故能在上线前拦下。

检查项 合格标准
包内结构 WEB-INF 与 web.xml 齐全,静态资源在应用根
上下文路径 包名与目标路径一致,根应用包名为 ROOT
环境差异 数据源与外部地址按环境区分,不带测试值
依赖完整性 应用库目录齐备,与容器公共库无版本冲突
发布确认 见到部署日志或管理端返回 OK 再切流量
回滚预案 上一版包仍在服务器上,回滚步骤演练过

另一个进阶做法是把应用放在 appBase 之外:webapps 目录只留给容器自带内容,业务应用用独立的 Context 片段指向外部路径。好处是升级容器目录时应用原地不动,迁移成本趋近于零——多实例运维(2.1 的 HOME 与 BASE 分离)时这个布局尤其顺手。

<!-- conf 目录下的独立片段文件:应用住在 appBase 之外 --> <Context docBase="/data/apps/order-app" path="/order"/>

注意 docBase 指向应用本体、path 声明访问路径,两者解耦后改名不搬家、搬家不改名。片段文件的文件名习惯上与应用对应,放在 conf 的对应虚拟主机子目录里即可生效。

本节要点回顾

  • 三种方式同一底层:都是 appBase 扫描建 Context,文件名即上下文路径,ROOT 名保留给根应用。
  • WEB-INF 是禁区:容器可读、浏览器 404,用户可见资源放外面,业务类与库放里面。
  • autoDeploy 默认开:便利是免重启,代价是类加载器泄漏、检测延迟与并发风险。
  • 发布要确认:以部署日志或 manager 返回的 OK 为准,切流量前先见证据。
  • 最小骨架六条命令:能徒手造应用,构建工具坏掉时也能应急上线。

住户搬进来了,下一节看它的两份登记表——web.xml 声明"我是谁、我有哪些组件",context.xml 声明"我需要什么资源"。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U