refactor: use nginx -s reload instead of systemd
- doc: add comment
This commit is contained in:
+40
-76
@@ -1,7 +1,7 @@
|
||||
# YMS Daemon 更新体系设计与实施计划
|
||||
|
||||
> 状态:研讨中,核心方向已收敛
|
||||
> 当前阶段:冻结 native/container 混合过渡、Docker standalone、OpenResty 蓝绿切换、客户 PC 交付工作台、离线包协议与 Jenkins 高频更新语义
|
||||
> 当前阶段:冻结 native/container 混合过渡、本地 Nginx gateway、Docker standalone、客户 PC 交付工作台、离线包协议与 Jenkins 高频更新语义
|
||||
> 本文档只描述设计和实施计划。除本文档外,现网代码、脚本、systemd、Nginx 和容器均未修改。
|
||||
|
||||
## 1. 目标
|
||||
@@ -319,9 +319,7 @@ daemon 内部先选择服务器已经明确登记的组件执行器,再进入
|
||||
├── frontend native directory executor
|
||||
├── frontend Docker executor
|
||||
└── nodeSsr Docker executor
|
||||
-> gateway controller
|
||||
├── 过渡期 host Nginx
|
||||
└── 目标态 OpenResty container
|
||||
-> host Nginx gateway controller
|
||||
```
|
||||
|
||||
本机部署配置必须为每个组件明确记录精确值 `native` 或 `container`。daemon 不根据文件名、目录、进程、systemd unit 或 Docker 容器自行推断运行类型。
|
||||
@@ -359,8 +357,8 @@ nodeSsr = container
|
||||
|
||||
客户服务器
|
||||
├── yms-daemon.service RPM 安装,宿主机常驻
|
||||
├── host Nginx 稳定入口,不随业务更新替换
|
||||
└── Docker Engine
|
||||
├── OpenResty gateway 稳定入口,不随业务更新替换
|
||||
├── frontend blue/green 镜像内包含 dist 和静态 Nginx
|
||||
├── backend blue/green
|
||||
└── nodeSsr blue/green
|
||||
@@ -371,7 +369,7 @@ nodeSsr = container
|
||||
```text
|
||||
客户服务器
|
||||
├── yms-daemon.service
|
||||
├── host Nginx 或 OpenResty gateway
|
||||
├── host Nginx gateway
|
||||
├── backend native blue/green JVM + systemd
|
||||
├── frontend native blue/green 版本目录
|
||||
└── Docker Engine
|
||||
@@ -444,10 +442,10 @@ yms-daemon
|
||||
└── version 查询 daemon 版本
|
||||
```
|
||||
|
||||
### 4.1 `serve`
|
||||
### 4.1 `ymsd`
|
||||
|
||||
```bash
|
||||
/usr/bin/yms-daemon serve
|
||||
/usr/bin/ymsd
|
||||
```
|
||||
|
||||
职责:
|
||||
@@ -457,7 +455,7 @@ yms-daemon
|
||||
- 为客户 PC 提供经过认证和授权的 WSS 控制与状态通道。
|
||||
- 串行执行更新事务。
|
||||
- 访问 Docker Engine API。
|
||||
- 通过 gateway controller 管理 host Nginx 或 OpenResty 配置和 graceful reload。
|
||||
- 通过 gateway controller 管理本地 Nginx 配置和 graceful reload。
|
||||
- 执行健康检查和业务验证。
|
||||
- daemon 或服务器重启后恢复未完成事务。
|
||||
|
||||
@@ -571,24 +569,18 @@ native 模式支持:
|
||||
|
||||
### 5.4 gateway
|
||||
|
||||
gateway 使用独立 OpenResty 容器,固定占用外部业务端口。它不随 `backend`、`frontend`、`nodeSsr` 的普通更新替换。
|
||||
gateway 固定使用客户服务器上的本地 Nginx,直接占用外部业务端口。它不随 `backend`、`frontend`、`nodeSsr` 的普通更新替换,也不进入 Docker Compose 或 Docker standalone 生命周期。
|
||||
|
||||
请求链路是分支结构:
|
||||
|
||||
```text
|
||||
浏览器
|
||||
-> OpenResty gateway
|
||||
├── / 和静态资源 -> frontend 静态容器
|
||||
├── /yms_services/ -> backend 容器
|
||||
-> host Nginx gateway
|
||||
├── / 和静态资源 -> frontend 静态目录或 frontend 容器
|
||||
├── /yms_services/ -> backend native unit 或容器
|
||||
└── 8910 -> nodeSsr 容器
|
||||
```
|
||||
|
||||
不存在以下链路:
|
||||
|
||||
```text
|
||||
OpenResty -> frontend Nginx -> backend
|
||||
```
|
||||
|
||||
frontend 静态 Nginx 只负责:
|
||||
|
||||
- 从镜像内 `/usr/share/nginx/html` 提供静态文件。
|
||||
@@ -596,56 +588,30 @@ frontend 静态 Nginx 只负责:
|
||||
- 静态缓存响应头。
|
||||
- 对不存在的资源返回可识别的真实错误。
|
||||
|
||||
backend 和 nodeSsr 由 OpenResty 直接代理。
|
||||
backend 和 nodeSsr 由本地 Nginx 直接代理。
|
||||
|
||||
### 5.5 gateway 分阶段迁移
|
||||
### 5.5 本地 Nginx 配置与切流
|
||||
|
||||
为避免 native 客户在安装 daemon 时被迫同时迁移全部运行结构,gateway 分为:
|
||||
daemon 只管理 `/etc/nginx/nginx.conf` 中冻结的 managed upstream 标记块,不覆盖整份 Nginx 配置。每次切流遵循:
|
||||
|
||||
```text
|
||||
第一阶段:复用现有宿主机 Nginx,由 daemon 管理配置检查、原子替换和 reload
|
||||
第二阶段:显式迁移到 OpenResty gateway 容器
|
||||
第三阶段:业务组件按 customer/site 计划逐个迁移到 container
|
||||
```
|
||||
1. 读取当前完整配置并确认唯一活动 backend 端口;
|
||||
2. 生成下一份完整配置,仅改变 daemon 管理的 upstream 标记块;
|
||||
3. 写入事务目录并保存更新前快照;
|
||||
4. 使用 `/usr/sbin/nginx -t -c /etc/nginx/nginx.conf` 验证;
|
||||
5. 原子替换配置文件;
|
||||
6. 使用 `/usr/sbin/nginx -s reload` 平滑加载;
|
||||
7. 通过健康检查和实际配置再次确认切流结果;
|
||||
8. 任一步失败时恢复更新前配置并再次执行配置检查。
|
||||
|
||||
host Nginx 和 OpenResty container 必须实现同一 gateway controller 语义:
|
||||
不使用 `systemctl reload nginx.service` 作为切流动作。systemd 只负责 Nginx 开机启动和进程守护,配置切换由 Nginx 原生命令完成。
|
||||
|
||||
- 生成完整下一配置。
|
||||
- 配置检查。
|
||||
- 原子替换。
|
||||
- graceful reload。
|
||||
- 恢复更新前配置。
|
||||
- 查询当前实际流量目标。
|
||||
Nginx 的两个 upstream 后端始终保留,daemon 只切换活动行的注释状态。`max_fails=1` 和 `fail_timeout=2s` 由现场配置固定管理,daemon 不在普通更新中改写。
|
||||
|
||||
单机从占用业务端口的 host Nginx 切换到 OpenResty container 是独立基础设施迁移。没有外部负载均衡时,不承诺该一次性迁移绝对零中断;迁移完成后的普通业务更新必须零停机。
|
||||
### 5.6 gateway 自身边界
|
||||
|
||||
### 5.6 为什么 gateway 目标态使用 OpenResty
|
||||
本地 Nginx 不属于三个业务组件的普通更新事务。daemon 不升级 Nginx 二进制、不安装 Lua、不接管客户未标记的配置段。Nginx 本身的升级、证书更新和全局配置变更由操作系统运维流程负责。
|
||||
|
||||
- 兼容现有 Nginx 路由和超时语义。
|
||||
- 支持 SSE、gRPC-Web、大文件上传和 graceful reload。
|
||||
- 后续可使用 Lua 增加灰度、鉴权、限流、审计和静态资源兼容。
|
||||
- 官方构建支持 `amd64` 和 `arm64/aarch64`。
|
||||
|
||||
第一版 Lua 不参与核心切流事务。切流依赖经过检查的配置文件和 OpenResty graceful reload,避免同时维护文件状态、共享内存状态和内部路由状态。
|
||||
|
||||
gateway:
|
||||
|
||||
- 不挂载 Docker Socket。
|
||||
- 不创建或删除业务容器。
|
||||
- 不接受更新包下发任意 Lua 文件。
|
||||
- Lua 代码只能随受控 gateway 镜像发布。
|
||||
|
||||
### 5.7 gateway 自身升级
|
||||
|
||||
gateway 自身升级不属于三个业务组件的普通更新。单机只有一个对外入口时,gateway 进程或整机故障无法提供绝对零中断。
|
||||
|
||||
gateway 自身零停机升级需要以下一种外部条件:
|
||||
|
||||
- 双机入口和外部负载均衡。
|
||||
- VRRP 或等价入口漂移机制。
|
||||
- Kubernetes Service。
|
||||
|
||||
第一版只保证三个业务组件的普通更新不停止 gateway。
|
||||
第一版只保证业务组件普通更新期间 Nginx 进程不停止,并保证 daemon 的配置切换使用语法检查、原子替换和 graceful reload。
|
||||
|
||||
## 6. 蓝绿双槽与零停机切流
|
||||
|
||||
@@ -684,7 +650,7 @@ systemd/Docker/目录 = 组件实际运行状态
|
||||
daemon 服务端 SQLite = 操作意图、过程、历史和恢复线索
|
||||
```
|
||||
|
||||
OpenResty 配置目录整体以 bind mount 提供给 gateway。不能只 bind mount 单个配置文件,否则宿主机原子重命名后容器可能继续引用旧 inode。host Nginx 由 daemon 直接管理宿主机配置目录。
|
||||
本地 Nginx 直接读取宿主机配置目录。daemon 只原子替换自身管理的配置文件,不覆盖未标记配置段。
|
||||
|
||||
### 6.3 单组件更新
|
||||
|
||||
@@ -698,9 +664,9 @@ OpenResty 配置目录整体以 bind mount 提供给 gateway。不能只 bind mo
|
||||
5. Docker inspect 取得实际容器信息
|
||||
6. daemon 直接检查 green 健康状态
|
||||
7. 生成完整的下一份 gateway 配置
|
||||
8. 在 gateway 内执行配置检查
|
||||
8. 使用 `/usr/sbin/nginx -t` 执行配置检查
|
||||
9. 同目录原子替换当前配置
|
||||
10. 向 OpenResty master 发送 HUP
|
||||
10. 使用 `/usr/sbin/nginx -s reload` 平滑加载
|
||||
11. 新 worker 把新请求发往 green
|
||||
12. 旧 worker 继续把已有连接交给 blue
|
||||
13. 通过 gateway 执行业务验证
|
||||
@@ -711,8 +677,8 @@ OpenResty 配置目录整体以 bind mount 提供给 gateway。不能只 bind mo
|
||||
核心切换:
|
||||
|
||||
```text
|
||||
旧 OpenResty worker -> blue -> 处理已有连接
|
||||
新 OpenResty worker -> green -> 接收新请求
|
||||
旧 Nginx worker -> blue -> 处理已有连接
|
||||
新 Nginx worker -> green -> 接收新请求
|
||||
```
|
||||
|
||||
配置检查失败时不得替换当前配置。reload 失败时旧 worker 继续使用旧配置,daemon 恢复更新前配置并再次检查。
|
||||
@@ -848,7 +814,7 @@ daemon 启动后:
|
||||
- native JAR 和 repack 后 frontend `dist/...` 文件的暂存、校验与双槽切换。
|
||||
- 镜像装载或拉取。
|
||||
- native 实例与 Docker 容器的 blue/green 并行运行。
|
||||
- host Nginx 与 OpenResty 的配置检查和 graceful reload。
|
||||
- 本地 Nginx 的配置检查和 graceful reload。
|
||||
- backend 新旧版本兼容。
|
||||
- Flyway 单次迁移边界。
|
||||
- SSE、上传和会话兼容。
|
||||
@@ -1191,7 +1157,7 @@ CREATED
|
||||
- 当前状态机阶段。
|
||||
- 每一步开始和结束时间。
|
||||
- systemd 或 Docker Engine 操作结果。
|
||||
- host Nginx 或 OpenResty 配置检查与 reload 结果。
|
||||
- 本地 Nginx 配置检查与 reload 结果。
|
||||
- 健康检查和业务验证结果。
|
||||
- drain 状态。
|
||||
- 提交、失败或回滚结果。
|
||||
@@ -1344,8 +1310,6 @@ native 过渡期还需要 daemon 管理的 backend blue/green unit。现有 `yms
|
||||
- Linux 构建验证 ELF 不存在非预期动态依赖。
|
||||
- 其他 ARM 目标取得客户精确 `GOARCH`、`GOARM` 或 `uname -m` 后再增加。
|
||||
|
||||
OpenResty gateway 也必须生成并验证 `linux/amd64` 和 `linux/arm64` 镜像。官方 `x86_64` OpenResty 预编译包存在 CPU 指令要求,客户老旧 CPU 的精确能力需要纳入现场采集和 CI 兼容基线。
|
||||
|
||||
## 13. 客户 PC 工作台与 GUI
|
||||
|
||||
客户 PC 使用同一 Windows 二进制的两个运行入口:
|
||||
@@ -1540,7 +1504,7 @@ Kubernetes executor 不在每个业务 Pod 中运行 daemon。它负责:
|
||||
|
||||
### 15.4 gateway
|
||||
|
||||
- host Nginx 或 OpenResty gateway 不存在或未运行。
|
||||
- 本地 Nginx 不存在或未运行。
|
||||
- 配置目录不可写。
|
||||
- 生成配置失败。
|
||||
- 配置检查失败。
|
||||
@@ -1625,7 +1589,7 @@ Kubernetes executor 不在每个业务 Pod 中运行 daemon。它负责:
|
||||
- [x] 确认 native 兼容层不执行现有更新脚本。
|
||||
- [x] 确认 Docker standalone 是 native 客户的主要迁移方向。
|
||||
- [x] 确认 frontend `dist` 在 CI 阶段进入 frontend 镜像。
|
||||
- [x] 确认 OpenResty 作为稳定 gateway。
|
||||
- [x] 确认本地 Nginx 作为稳定 gateway。
|
||||
- [x] 确认业务组件使用 blue/green 和 graceful reload 零停机切流。
|
||||
- [x] 确认第一版不使用 Lua shared dict 作为核心切流状态。
|
||||
- [x] 确认开发环境使用同一更新体系进行高频更新。
|
||||
@@ -1667,7 +1631,7 @@ Kubernetes executor 不在每个业务 Pod 中运行 daemon。它负责:
|
||||
- [ ] 实现 Docker Engine API 客户端和兼容性检查。
|
||||
- [ ] 实现镜像 digest 校验。
|
||||
- [ ] 实现 blue/green 统一生命周期。
|
||||
- [ ] 实现 OpenResty gateway controller 的配置生成、检查、原子替换和 HUP。
|
||||
- [ ] 实现本地 Nginx gateway controller 的配置生成、检查、原子替换和 `/usr/sbin/nginx -s reload`。
|
||||
- [ ] 实现 backend、frontend、nodeSsr 健康检查。
|
||||
- [ ] 实现基于 SQLite 意图、gateway 配置和 systemd/Docker/文件实际状态的重启恢复。
|
||||
- [ ] 在开发环境按 native 文件 SHA-256 或 container digest 完成高频更新闭环。
|
||||
@@ -1740,7 +1704,7 @@ Kubernetes executor 不在每个业务 Pod 中运行 daemon。它负责:
|
||||
6. Docker standalone 是 native 客户向容器化迁移的主要方向。
|
||||
7. container 制品使用 OCI digest 作为身份,不依赖 tag 判断版本;native 制品使用 manifest 声明的文件路径、长度和 SHA-256。
|
||||
8. container frontend 的 `dist` 在 CI 阶段烘焙进 frontend 镜像;native frontend 由 repack 展开源归档,客户 manifest 逐文件声明 `dist/...` 的路径、长度和 SHA-256,daemon 把这些文件写入非活动版本目录。
|
||||
9. 目标态由 OpenResty 作为稳定 gateway;过渡期允许 host Nginx 实现同一 gateway controller 语义;frontend 静态 Nginx 不代理 backend。
|
||||
9. 目标态由客户服务器本地 Nginx 作为稳定 gateway;frontend 静态 Nginx 不代理 backend。
|
||||
10. 三个业务组件通过 blue/green 双槽和 gateway graceful reload 实现普通更新零停机。
|
||||
11. 第一版核心切流不引入动态 Lua 路由 shared dict 和独立路由数据库。
|
||||
12. 开发环境必须使用同一 daemon;container 验证同一次 multi-platform 构建的实际平台 digest,native 验证 backend JAR 或 frontend 源归档及展开文件的 SHA-256,并复用同一切流和回滚执行器进行高频更新。
|
||||
@@ -1778,7 +1742,7 @@ Kubernetes executor 不在每个业务 Pod 中运行 daemon。它负责:
|
||||
44. `daemon.environment` 固定为必填机器级字段,只接受精确值 `dev`、`prod`;它只选择 container 镜像获取行为,`dev` 为 Registry pull,`prod` 为 repack ZIP load。
|
||||
45. 第一阶段 backend native 配置精确使用 `[backend]`、`[backend.slot.8080]` 和 `[backend.slot.8081]`;key、必填规则和精确值以 2.9 节为准,loader 不提供配置默认值。
|
||||
46. daemon 服务端路径固定为:Unix Socket `/run/yms-daemon/yms-daemon.sock`、进程锁 `/run/yms-daemon/yms-daemon.lock`、SQLite `/var/lib/yms-daemon/yms-daemon.db`、事务工作目录 `/var/lib/yms-daemon/work`、本地日志 `/var/log/yms-daemon/yms-daemon.log`。
|
||||
47. 当前 native 过渡 gateway 固定管理 `/etc/nginx/nginx.conf` 中唯一一组 `# yms-update managed upstream begin/end` 标记,Nginx 可执行文件固定为 `/usr/sbin/nginx`,systemd unit 固定为 `nginx.service`;配置完整原子替换后执行 `/usr/sbin/nginx -t` 和 `systemctl reload`,任一步失败恢复替换前完整配置。
|
||||
47. 当前 gateway 固定管理 `/etc/nginx/nginx.conf` 中唯一一组 `# yms-update managed upstream begin/end` 标记,Nginx 可执行文件固定为 `/usr/sbin/nginx`,systemd unit 固定为 `nginx.service`;配置完整原子替换后执行 `/usr/sbin/nginx -t` 和 `/usr/sbin/nginx -s reload`,任一步失败恢复替换前完整配置。
|
||||
48. 第一次旧 unit 运行态迁移固定映射为 8080=`yms.service`、8081=`ymsback.service`;Nginx 当前接流端口对应的旧 unit 和 `yms-backend@<port>.service` 必须恰好一个处于运行态,否则拒绝更新。
|
||||
49. backend native 更新输入分为 `repack-zip` 和 `native-jar`;前者由 `-f` 提交,后者由 `--native-jar` 提交,二者互斥且不通过扩展名推断。直传 JAR 使用完整文件 SHA-256 作为幂等身份,在 `/home/yms/lib/releases` 下保存为 `direct/<SHA-256前12位>/<原始JAR文件名>`;目录名精确取完整小写十六进制 SHA-256 的前 12 位,完整 SHA-256 继续用于幂等和内容校验,目录冲突时拒绝覆盖。直传 JAR 复用与 repack ZIP 相同的双槽、健康检查、切流、提交和补偿流程。
|
||||
50. backend native 零停机重启命令固定为 `yms-daemon restart --service backend`,可附加 `--quite`。restart 使用当前接流 release 创建独立事务并轮转到非活动槽,不调用 `systemctl restart`,也不重新上传 JAR;当前 JAR 已在 release 目录时直接复用,兼容入口仍是普通文件时按内容身份导入 release 目录。未完成 restart 由同一命令恢复,其他未完成事务阻止新 restart。
|
||||
@@ -1795,7 +1759,7 @@ Kubernetes executor 不在每个业务 Pod 中运行 daemon。它负责:
|
||||
6. native backend 从现有 `/home/yms/bin/env/yms.env` 迁移到 `/home/yms/conf` 外挂配置的时机和兼容规则。
|
||||
7. native frontend 双版本目录的精确值。
|
||||
8. gateway 容器镜像、配置目录、Docker network、blue/green 容器名和 label 的精确值。
|
||||
9. host Nginx 和 OpenResty 配置 reload 成功的确认方式。
|
||||
9. 本地 Nginx 配置检查和 `/usr/sbin/nginx -s reload` 成功的确认方式。
|
||||
10. SSE 和上传的最大 drain 时间与强制结束规则。
|
||||
11. 三个组件的旧槽保留时间、磁盘清理和镜像清理规则。
|
||||
12. `/home/yms/tmp` 的内部子目录、容量限制、保留时间和异常文件清理规则。
|
||||
|
||||
Reference in New Issue
Block a user