FtpTool/docs/ftp-sync-tool-design.md
2026-04-28 17:00:58 +08:00

263 lines
5.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 基于 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 -> PROD 支持:
- `git.repo.scan-branch`:单分支同步
- `git.repo.scan-branch-pattern`:批量扫描同步
- **分支名本身就是 `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. 解析 `scan-branch``scan-branch-pattern`
2. 逐个拉取命中的版本分支
3. 读取当前 `HEAD revision`
4.**分支名** 作为业务版本号 `sourceVersion`
5. 导出该分支工作树
6. 解析所有 `airportId/appName/fileName` 配置项
7. 调用生产 `pushConfig`
8. 成功后更新 `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.scan-branch-pattern=^R_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>` 动态分支写回**