- Git -> PROD 改为按 branch 作为 configVersion - 按 airportId/appName/fileName 目录结构解析 pushConfig 参数 - PROD -> Git 改为写入 snapshot-branch/<configVersion> 动态分支 - pullConfig 支持 configVersion/fileName 可选过滤 - 抽出 ConfigCryptoService,统一收口加解密扩展点 - ackFail 落库增加重试上下文,支持按 airportId/appName/configVersion/fileName 定向重拉 - 同步更新测试、接口文档和 current.md
259 lines
5.6 KiB
Markdown
259 lines
5.6 KiB
Markdown
# 基于 Git 版本分支的配置双向同步工具设计方案
|
||
|
||
## 1. 文档目的
|
||
|
||
本文档说明当前 Git 直连同步工具的目标模型、仓库约定和双向同步流程。
|
||
|
||
适用范围:
|
||
|
||
- 生产环境定时从开发 Git 拉取某个版本分支,并调用生产 `pushConfig` 下发配置
|
||
- 生产环境定时从生产 `pullConfig` 拉取当前配置,并回写到 Git 快照分支
|
||
- FTP 已退出主运行面
|
||
|
||
## 2. 核心约束
|
||
|
||
### 2.1 技术约束
|
||
|
||
- JDK:`1.8`
|
||
- Spring Boot:`2.7.18`
|
||
- 状态库:`H2`
|
||
- Git 操作:`JGit`
|
||
|
||
### 2.2 网络与部署约束
|
||
|
||
- 生产环境可以读取开发 Git
|
||
- 生产环境需要能向 Git 推送快照分支
|
||
- 生产环境需要能访问生产 `push/pull/login` 接口
|
||
- FTP 不再参与同步流程
|
||
|
||
## 3. 总体架构
|
||
|
||
推荐拓扑:
|
||
|
||
```text
|
||
开发 Git 仓库 <----> 生产环境 prod-agent <----> 生产系统 push/pull 接口
|
||
```
|
||
|
||
当前只保留一个正式运行角色:
|
||
|
||
- `prod-agent`
|
||
|
||
## 4. Git 仓库约定
|
||
|
||
## 4.1 版本分支约定
|
||
|
||
当前需求下:
|
||
|
||
- 一个待发布版本对应一个 Git 分支
|
||
- `git.repo.scan-branch` 直接配置为当前待同步版本分支
|
||
- **分支名本身就是 `configVersion`**
|
||
|
||
示例:
|
||
|
||
- `R_XXX_V3.0.3_XXX`
|
||
- `R_XXX_V3.0.4_XXX`
|
||
|
||
### 4.2 分支内目录约定
|
||
|
||
每个版本分支内部必须按以下结构组织:
|
||
|
||
```text
|
||
<airportId>/<appName>/<模块内文件相对路径>
|
||
```
|
||
|
||
示例:
|
||
|
||
```text
|
||
R_XXX_V3.0.3_XXX
|
||
├─ PEK
|
||
│ └─ monitor
|
||
│ ├─ application.yml
|
||
│ └─ jobs/sync-job.json
|
||
└─ SHA
|
||
└─ gate
|
||
└─ gate-rule.json
|
||
```
|
||
|
||
### 4.3 快照分支约定
|
||
|
||
当前实现使用动态快照分支:
|
||
|
||
- `git.repo.snapshot-branch=config-prod-snapshot`
|
||
|
||
`PROD -> Git` 会把拉回的数据提交到:
|
||
|
||
```text
|
||
git.repo.snapshot-branch/<configVersion>
|
||
```
|
||
|
||
目录结构同样为:
|
||
|
||
```text
|
||
<airportId>/<appName>/<fileName>
|
||
```
|
||
|
||
## 5. 两条核心链路
|
||
|
||
### 5.1 Git -> PROD
|
||
|
||
目标:
|
||
|
||
- 将当前版本分支中的配置同步到生产
|
||
|
||
流程:
|
||
|
||
1. 拉取 `git.repo.scan-branch`
|
||
2. 读取当前 `HEAD revision`
|
||
3. 以 **分支名** 作为业务版本号 `sourceVersion`
|
||
4. 导出该分支工作树
|
||
5. 解析所有 `airportId/appName/fileName` 配置项
|
||
6. 调用生产 `pushConfig`
|
||
7. 成功后更新 `sync_task` 和 `sync_checkpoint`
|
||
|
||
说明:
|
||
|
||
- `revision` 仅用于日志和 staging 目录隔离
|
||
- 当前不再使用 `commit SHA` 作为下发版本号
|
||
|
||
### 5.2 PROD -> Git
|
||
|
||
目标:
|
||
|
||
- 将生产当前配置快照回写到 Git
|
||
|
||
流程:
|
||
|
||
1. 调用生产 `pullConfig`
|
||
2. 把返回项落盘为 `airportId/appName/fileName`
|
||
3. 计算内容哈希和来源版本
|
||
4. 提交到 `git.repo.snapshot-branch/<configVersion>`
|
||
5. 成功后更新 `sync_task` 和 `sync_checkpoint`
|
||
|
||
## 6. 接口参数与路径映射
|
||
|
||
Git -> PROD 时,每个文件都映射为一条 `pushConfig` 记录:
|
||
|
||
| Git 信息 | 接口字段 |
|
||
| --- | --- |
|
||
| 分支名 | `configVersion` |
|
||
| 路径第 1 段 | `airportId` |
|
||
| 路径第 2 段 | `appName` |
|
||
| 路径第 3 段及之后 | `fileName` |
|
||
| 文件内容 | `configContent` |
|
||
|
||
例如:
|
||
|
||
```text
|
||
PEK/monitor/jobs/sync-job.json
|
||
```
|
||
|
||
会变成:
|
||
|
||
```json
|
||
{
|
||
"airportId": "PEK",
|
||
"appName": "monitor",
|
||
"configVersion": "R_XXX_V3.0.3_XXX",
|
||
"fileName": "jobs/sync-job.json"
|
||
}
|
||
```
|
||
|
||
## 7. 增量策略
|
||
|
||
当前 Git -> PROD 已实现:
|
||
|
||
- 首次同步全量
|
||
- 后续优先按文件哈希做最小增量
|
||
- 检测到删除时自动回退为全量
|
||
|
||
并且 baseline 已按版本分支隔离:
|
||
|
||
```text
|
||
work/baseline/git-to-prod/<scan-branch>/
|
||
```
|
||
|
||
避免不同版本分支之间相互污染。
|
||
|
||
## 8. 状态设计
|
||
|
||
当前状态表:
|
||
|
||
- `sync_checkpoint`
|
||
- `sync_task`
|
||
- `prod_pull_ack`
|
||
|
||
说明:
|
||
|
||
- `sync_checkpoint`:记录某方向最后一次成功版本和哈希
|
||
- `sync_task`:记录每次同步任务和重试状态
|
||
- `prod_pull_ack`:记录 `pullConfig` 的 `ackSuc/ackFail` 回传状态
|
||
|
||
## 9. 幂等设计
|
||
|
||
当前幂等键:
|
||
|
||
```text
|
||
direction + sourceVersion + contentHash
|
||
```
|
||
|
||
作用:
|
||
|
||
- 同一版本分支下同一内容不会重复推送
|
||
- 同一生产快照不会重复回写 Git
|
||
|
||
## 10. 当前配置口径
|
||
|
||
关键 Git 配置:
|
||
|
||
```properties
|
||
git.repo.scan-branch=R_XXX_V3.0.3_XXX
|
||
git.repo.snapshot-branch=config-prod-snapshot
|
||
git.repo.commit-message-prefix=sync(prod->git)
|
||
```
|
||
|
||
关键接口配置:
|
||
|
||
```properties
|
||
prod.api.base-url=https://prod.example.com
|
||
prod.api.push-path=/pic_bus_manage_monitor/configSync/pushConfig
|
||
prod.api.pull-path=/pic_bus_manage_monitor/configSync/pullConfig
|
||
prod.api.login-path=/pic_bus_manage_monitor/pam-monitor/login
|
||
prod.api.token=replace-me
|
||
prod.api.token-header-name=token
|
||
prod.api.airport-id=
|
||
prod.api.app-name=
|
||
prod.api.pull-config-version=
|
||
prod.api.pull-file-name=
|
||
```
|
||
|
||
说明:
|
||
|
||
- `prod.api.airport-id`、`prod.api.app-name` 当前只作为 `pullConfig` 可选过滤参数
|
||
- 它们不再承担 Git -> PROD 的参数组装职责
|
||
- `prod.api.pull-config-version`、`prod.api.pull-file-name` 可用于进一步缩小 `pullConfig` 拉取范围
|
||
|
||
## 11. 当前已实现能力
|
||
|
||
- `pushConfig`:`POST + JSON 数组`
|
||
- `pullConfig`:`GET + JSON 响应`
|
||
- `login`:自动获取并缓存 token
|
||
- `ackSuc/ackFail`:已接入请求回传与本地落库
|
||
- Git -> PROD:已支持最小增量推送
|
||
- 管理接口:
|
||
- `GET /api/admin/sync/overview`
|
||
- `GET /api/admin/sync/tasks/recent`
|
||
- `GET /api/admin/sync/tasks/failed`
|
||
|
||
## 12. 当前未完成项
|
||
|
||
- 将 `ConfigCryptoService` 的透传实现替换为正式加解密算法
|
||
|
||
## 13. 结论
|
||
|
||
当前文档口径应统一为:
|
||
|
||
- **版本用 Git 分支表达**
|
||
- **机场和模块用目录表达**
|
||
- **接口参数由路径直接解析**
|
||
- **快照按 `git.repo.snapshot-branch/<configVersion>` 动态分支写回**
|