feat: backend executor implement

This commit is contained in:
2026-08-16 17:12:06 +08:00
parent 390e0565d3
commit 7755da72e7
31 changed files with 2762 additions and 184 deletions
+40 -8
View File
@@ -254,6 +254,9 @@ RPM 安装阶段创建 `/home/yms/dump`,属主和用户组固定为 `root:root
daemon 本机配置文件固定为 `/etc/yms-daemon/yms-daemon.toml`。第一阶段已经冻结并实现 backend native 配置:
```toml
[daemon]
environment = "prod"
[backend]
type = "native"
release_dir = "/home/yms/lib/releases"
@@ -273,12 +276,34 @@ health_endpoint = "http://127.0.0.1:8081/yms/actuator/health"
字段规则固定为:
- `daemon.environment` 是机器级行为标记,只接受精确值 `dev``prod``dev` 使 container 从 Registry pull`prod` 使 container 从 repack ZIP load。该字段不改变 native 更新、健康检查、切流、事务或回滚行为。
- table 和 key 必须与上例逐字一致;大小写不同、未知字段、未知槽位和重复字段全部拒绝。
- `backend.type` 第一阶段只接受精确值 `native`container 配置在其完整 table 和 key 冻结后扩展,daemon 不根据现场状态自动选择。
- `backend.type` 接受精确值 `native``container`daemon 不根据现场状态自动选择。
- `release_dir``active_jar`、两个槽位的 `unit``jar``health_endpoint` 必须与上例完全相同。
- `systemctl_path` 必须由现场明确填写干净的绝对路径;当前现场填写 `/bin/systemctl`,精确检查结果为 `/usr/bin/systemctl` 的服务器填写 `/usr/bin/systemctl`
- loader 不补默认值,不改写路径,不改写大小写,不根据端口拼接 unit、JAR 路径或健康地址。
- RPM 安装示例文件位于 `packaging/etc/yms-daemon/yms-daemon.toml`RPM spec 接入时将其安装到固定路径
- RPM 安装示例文件位于 `packaging/etc/yms-daemon/yms-daemon.toml`RPM spec 已将其以 `noreplace` 语义安装到固定路径,跨架构打包入口为 `packaging/rpm/build-rpm.sh`
backend container 开发环境配置已经冻结为:
```toml
[daemon]
environment = "dev"
[backend]
type = "container"
systemctl_path = "/bin/systemctl"
[backend.slot.8080]
container_name = "backend-8080"
health_endpoint = "http://127.0.0.1:8080/yms/actuator/health"
[backend.slot.8081]
container_name = "backend-8081"
health_endpoint = "http://127.0.0.1:8081/yms/actuator/health"
```
container slot 固定挂载 `/home/yms/conf/yms.yaml:/app/config/yms.yaml:ro``/home/yms/tmp:/home/yms/tmp`,固定注入 `SERVER_PORT``SPRING_CONFIG_LOCATION=file:/app/config/yms.yaml`,固定使用 host network、root 用户、restart policy `no` 和 9000 秒 graceful stop 上限。外挂 `yms.yaml` 是唯一 Spring Boot 配置入口,必须同时包含 Spring Boot 配置和原 config 文件中的业务配置,不再追加加载 JAR 内默认配置。开发更新入口固定为 `yms-daemon update --service backend --container-image <完整tag引用>`daemon pull 后读取实际 RepoDigest,并将事务后续步骤固定到 digest 引用。
## 3. 总体架构
@@ -692,6 +717,8 @@ OpenResty 配置目录整体以 bind mount 提供给 gateway。不能只 bind mo
配置检查失败时不得替换当前配置。reload 失败时旧 worker 继续使用旧配置,daemon 恢复更新前配置并再次检查。
全新机器首次部署必须同时满足:SQLite 不存在已提交的 container backend 部署记录、不存在历史 `COMMITTED` container backend 事务,并且 `backend-8080``backend-8081` 均不存在。daemon 在 Nginx 当前未接流的槽位创建并启动首个容器,健康检查通过后切流并提交部署记录;因为没有旧容器,所以不执行 drain 和停止步骤。已提交记录、Nginx 和容器现场任一不一致时拒绝更新,不得降级为首次部署;`FAILED``ROLLED_BACK` 首装事务不表示机器曾成功部署(见第 17 节决策 51)。
native backend 使用相同切流步骤,但准备阶段替换为:
```text
@@ -879,6 +906,8 @@ frontend 源归档本身不进入当前客户 ZIP,不能在客户 manifest 中
两种方式在进入执行器前必须归一为同一份经过校验的组件安装描述,后续步骤完全相同。
container 镜像获取方式只由本机 TOML 的 `daemon.environment` 选择:精确值 `dev` 执行 Registry pull,精确值 `prod` 执行 repack ZIP load。该标记不附带其他 CLI、签名、更新或重启限制。
### 7.4 环境策略差异
| 策略 | 开发环境 | 客户现场 |
@@ -1746,12 +1775,15 @@ Kubernetes executor 不在每个业务 Pod 中运行 daemon。它负责:
41. 当前客户服务器的 systemctl 可执行文件绝对路径为 `/bin/systemctl`;其他服务器使用其本机明确配置的绝对路径,daemon 不自行尝试替代路径。
42. native backend unit 使用 `Type=simple` 直接执行 `/usr/bin/java`,不调用启动脚本;堆转储目录固定为 `/home/yms/dump`,其属主和用户组固定为 `root:root`、权限固定为 `0755` 并由 RPM 创建;JVM 错误日志固定为 `/home/yms/log/hs_err_pid%p.log`stdout 和 stderr 进入 journal`TimeoutStopSec` 固定为 `150min`
43. daemon 本机配置文件固定为 `/etc/yms-daemon/yms-daemon.toml`,格式固定为 TOML;使用纯 Go 的 `github.com/pelletier/go-toml/v2` 严格解码,并在解码前逐字校验完整键树,拒绝大小写变化、未知字段、未知槽位和重复字段,保持 `CGO_ENABLED=0`
44. 第一阶段 backend native 配置精确使用 `[backend]``[backend.slot.8080]``[backend.slot.8081]`;key、必填规则和精确值以 2.9 节为准,loader 不提供配置默认值
45. 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`
46. 当前 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. 第一次旧 unit 运行态迁移固定映射为 8080=`yms.service`、8081=`ymsback.service`;Nginx 当前接流端口对应的旧 unit 和 `yms-backend@<port>.service` 必须恰好一个处于运行态,否则拒绝更新
48. 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 相同的双槽、健康检查、切流、提交和补偿流程
49. backend native 零停机重启命令固定为 `yms-daemon restart --service backend`,可附加 `--quite`。restart 使用当前接流 release 创建独立事务并轮转到非活动槽,不调用 `systemctl restart`,也不重新上传 JAR;当前 JAR 已在 release 目录时直接复用,兼容入口仍是普通文件时按内容身份导入 release 目录。未完成 restart 由同一命令恢复,其他未完成事务阻止新 restart
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`,任一步失败恢复替换前完整配置
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。
51. container backend 的 `update --service backend --container-image` 仅在 SQLite 不存在已提交部署记录、不存在历史 `COMMITTED` container backend 事务,且 `backend-8080``backend-8081` 都不存在时按首次部署处理:目标固定为 Nginx 当前未接流的槽位,容器启动并通过健康检查后执行一次正常切流,随后原子提交事务状态和活动容器部署记录;因为不存在 previous 容器,所以不执行 drain 和停止步骤。存在已提交记录或历史 `COMMITTED` container backend 事务时,容器、记录和 Nginx 任一不一致均按状态漂移拒绝更新,不静默按首次部署处理;`FAILED``ROLLED_BACK` 首装事务不构成成功部署证据。该语义只覆盖 container backendnative backend 首装保持现状。
52. 外部步骤一次执行失败后,同一条命令在本次调用内不自动重试。交付人员修复 Nginx、systemd、容器运行时或文件系统后再次人工执行命令时,协调器必须先 inspect 已失败步骤:`APPLIED` 直接补记成功,`NOT_APPLIED` 才重新 Apply`UNKNOWN` 继续拒绝推进。回滚完成为 `ROLLED_BACK` 后,再次提交相同载荷时原子归档旧事务幂等键并创建新事务;历史 `COMMITTED` 事务仍保持幂等返回。container 首装回滚遗留的已停止目标容器由新事务准备阶段检查并清理,不要求人工删除。
## 18. 当前必须继续研讨的精确问题