LabHub
学习 学习路径 课程

Tomcat 与 nginx 运维

WAR 部署的实际情况与并行部署(Parallel Deployment)

在 LabHub 中继续学习

一句话总结

单纯复制WAR的部署中存在一个名为404的漏洞,Tomcat已经有填补该漏洞的手段(##버전虽然有并行分发),但大多数现场都不知道。

概念图: 开放的第一天上午九点 · 复制过程中,Tomcat开始展开。 · webapps/order/目录会先被删除。 · 删除失败

为什么这是问题?

停止发布虽然安全,但在此期间服务会停止。如果只覆盖WAR进行无中断操作,直到展开结束为止,路径会显示为404,这段时间越是班级越多,可能超过30秒。不能简单地认为时间短的原因是,这30秒发生在开放的第一天上午九点

而且失败很安静。复制过程中,Tomcat开始展开,解开了一半的WAR,如果失败的话,会留在日志中,但发布脚本的结束代码是0。发布的人相信自己成功了,然后下班。

WAR是如何分发的?

webapps/order.war复制的话汤姆猫会webapps/order/解开后/order通过路线提供服务。 这个autoDeploy="true"的动作。虽然方便,但在运营中却存在陷阱。

并行分发——Tomcat原有的无中断手段

Tomcat有一个不太为人知的功能。在文件名中##버전加上的话 可以在同一上下文路径上同时上传多个版本。

webapps/order##001.war   ← 기존 버전
webapps/order##002.war   ← 새 버전

在这种状态下,Tomcat会这样移动。

也就是说,不中断会话,直接跳转到新版本。在L4前端取出并插入服务器 在无法进行传统无中断部署的单一WAS环境中,这张卡相当有用。

版本字符串会通过字符串比较进行排序##1##2##10像这样用的话 ##10这个##2看着继续向前走。##001像这样填写0或 ##2026-08-19_1430使用相同的时间戳。

即便如此,在停止分发的情况下

并行分发不是万能的。在以下情况下不能使用。

所以实际判断是这样的: 如果只有画面和逻辑变更,则进行并行发布;如果模式、部署和全域状态交织在一起,则停止发布。

WAR和可执行JAR有什么不同

最近的新开发用Spring Boot fat jar,现有系统都是WAR。 在同一个组织中两个人共存是很常见的,所以整理一下差异比较好。

项目 WAR + 外部 Tomcat 可执行 JAR (内置 Tomcat)
分发单位 WAR文件 JAR文件
Tomcat版本 由服务器管理员管理(多个应用程序共享) 应用程序在运行(每个应用程序可能有所不同)
端口 server.xml 执行参数 / 属性
放置多个应用程序 在一个WAS上放置多个上下文 打开多个进程
还原 更换为以前的WAR 更换为以前的JAR进行进程更换
无中断 并行部署或L4 进程更换 + LB
运营标准 WAS标准程序书 流程/容器标准程序书

运营组织的标准程序书写在哪一边决定了实际的选择。 即使从技术上讲JAR很方便,但在以WAS单位进行监控、机动、备份程序标准化的组织中 因为一个JAR,我们需要重新制定程序。这可能比技术优势的成本还要高。

分发脚本必须具备的最低条件

现场可以使用的分发脚本做到这个程度。

  1. 因子验证 — WAR文件是否实际存在,不是0字节
  2. 备份 — 将当前发布版附上时间戳保存
  3. 原子性布局 — 用临时名称复制后mv
  4. 展开等待 — 持续 polling,直到上下文在最大 N 秒内响应。
  5. 验证 — 健康检查URL是200,版本字符串是否符合预期值
  6. 失败时立即中断 — 5次失败时不报告为部署成功

4次“进展等待”特别重要。cp紧接着curl做的话还是404。 也看过判定为失败并进行回溯的脚本,相反,没有等待 我看过更多输出“部署完成”后结束的脚本。 后者将失败的部署视为成功。这更糟糕。

在现场相遇的样子

所以分配脚本必须具备的最低条件已经确定。用其他名字复制后mv首先将名称改成原子,等到展开结束为止,确认实际响应是否为200后输出终止代码。复制后立即确认的话,因为还在展开中,所以会失败,但经常误认为这是“部署失败”而退回。