FtpTool/docs/ftp-sync-tool-design.md
dark dcfdc83444 refactor: 收敛同步工具为 Git 直连单 prod-agent 架构
- 重写主设计文档与详细设计文档,移除 FTP 中转方案口径
- 新增 Git 直连架构设计文档,明确单 prod-agent 部署模式
- 将生产侧主同步流程切换为 Git -> PROD 和 PROD -> Git 两条直连链路
- 新增正式调度任务 GitToProdSyncJob 与 ProdToGitSnapshotJob
- 移除 commons-net 主依赖并将 FTP 能力退出主运行面
- 清理 application.properties 中 FTP/ACK 相关公共配置
- 收敛 SyncProperties,删除 FTP 远端目录与 ACK 扫描字段
- 精简 schema.sql,移除 sync_ack 表,仅保留 sync_checkpoint 与 sync_task
- 将 dev-agent、FTP、ACK 相关旧类降级为退役占位实现
- 调整项目命名与默认配置,统一到 Git 直连架构
- 完成编译验证
2026-04-20 14:30:43 +08:00

11 KiB
Raw Blame History

基于 Git 直连的配置双向同步工具设计方案

1. 文档目的

本文档用于说明一套基于 Git 直连的配置同步工具设计方案,满足以下目标:

  • 生产环境定时从开发 Git 拉取新配置,并调用生产 push 接口导入生产
  • 生产环境定时从生产 pull 接口拉取当前配置,并回写到开发 Git
  • 在 FTP 不再使用的前提下,简化整体架构、降低维护成本

2. 已知约束

2.1 技术约束

  • JDK1.8
  • Spring Boot2.7.18
  • 轻量数据库:H2 或同类开源可商用数据库
  • 其他依赖必须为开源可商用组件

2.2 网络与部署约束

  • 生产环境可以访问开发 Git 仓库
  • 生产环境需要能够调用生产系统 push/pull 接口
  • FTP 不再使用

建议先确认一个关键前提:

  • 生产环境是否对开发 Git 具备“读 + 写”权限

说明:

  • 如果生产环境只能读取 Git无法推送分支那么“生产 -> 开发 Git”这条链路不能闭环
  • 如果生产环境可以读取和推送 Git则整套同步可以收敛为单点部署

3. 新架构结论

在新条件下,不再推荐“双端代理 + FTP 中转”。

推荐改为:

  • 单端代理 + Git 直连 + 本地状态库

即只在生产环境部署一套同步服务:

  • Sync-Agent-Prod

它同时承担两类任务:

  1. 从开发 Git 拉取配置,推送到生产
  2. 从生产 pull 接口拉取配置,回写到开发 Git

整体结构如下:

开发 Git 仓库 <----> 生产环境 Sync-Agent-Prod <----> 生产系统 push/pull 接口

4. 为什么要改成单端部署

新架构相比旧方案有明显优势:

  • 去掉 FTP中转链路减少一跳
  • 去掉打包上传、轮询下载、ACK 回执等中间环节
  • 部署节点减少为 1 个,运维更简单
  • 故障点减少,排查路径更短
  • 数据流更直接,状态一致性更容易控制

5. 总体方案

推荐在生产环境部署唯一同步实例:

  • Sync-Agent-Prod

其职责如下:

  • 拉取开发 Git 主配置分支
  • 检查是否存在待下发的新版本
  • 调用生产 push 接口导入配置
  • 定时调用生产 pull 接口获取当前生产配置
  • 将生产配置写回 Git 快照分支
  • 使用 H2 记录同步状态、检查点、失败记录

6. 技术选型

分类 选型 说明
运行时 JDK 1.8 满足约束
框架 Spring Boot 2.7.18 主体框架
调度 Spring Scheduling 实现定时任务
重试 Spring Retry 失败重试
数据库 H2 File Mode 持久化检查点与任务状态
Git 操作 JGit 生产环境直接读写 Git
HTTP 调用 RestTemplate 调用生产 push/pull 接口
JSON Jackson 标准序列化
日志 SLF4J + Logback 默认日志能力

说明:

  • FTP 客户端依赖在新方案里已经不是核心能力
  • 标准同步包、FTP 目录、ACK 文件等设计可以整体下线

7. 部署模式

7.1 推荐模式

推荐只部署:

  • prod-agent

不再需要:

  • dev-agent
  • FTP 中转服务

7.2 运行位置

同步工具建议运行在生产环境可控节点上,要求:

  • 能访问开发 Git
  • 能访问生产 push/pull 接口
  • 能持久化本地 H2 文件数据库

8. 两条核心链路

8.1 链路一:开发 Git -> 生产 push 接口

用途:

  • 将开发配置分支中的新配置同步到生产环境

流程如下:

  1. Sync-Agent-Prod 定时拉取开发 Git 指定分支
  2. 获取最新提交版本号,例如 Git Commit ID
  3. 判断该版本是否已成功同步
  4. 如果未同步,则导出配置目录
  5. 调用生产 push 接口导入配置
  6. 成功后更新本地检查点和任务状态

建议时序图如下:

sequenceDiagram
    participant G as Git(开发)
    participant P as Sync-Agent-Prod
    participant API as 生产Push接口

    P->>G: 定时 pull config-dev-main
    P->>P: 判断是否有新 commit
    P->>P: 导出配置目录
    P->>API: 调用 push 接口
    API-->>P: 返回处理结果
    P->>P: 更新 sync_task / checkpoint

8.2 链路二:生产 pull 接口 -> 开发 Git

用途:

  • 将当前生产配置快照回写到开发 Git用于镜像、审计、回溯

流程如下:

  1. Sync-Agent-Prod 定时调用生产 pull 接口
  2. 将返回结果标准化并计算内容哈希
  3. 判断该版本或哈希是否已同步
  4. 如果未同步,则切换到生产快照分支
  5. 写入配置文件
  6. 提交 commit 并 push 到开发 Git
  7. 成功后更新本地检查点和任务状态

建议时序图如下:

sequenceDiagram
    participant API as 生产Pull接口
    participant P as Sync-Agent-Prod
    participant G as Git(开发)

    P->>API: 定时调用 pull 接口
    API-->>P: 返回当前生产配置
    P->>P: 标准化并计算 hash/version
    P->>G: checkout config-prod-snapshot
    P->>G: commit + push
    P->>P: 更新 sync_task / checkpoint

9. Git 分支策略

这个设计点仍然必须保留。

不建议将“开发配置推生产”和“生产配置回写 Git”使用同一个 Git 分支,否则非常容易形成同步闭环。

推荐分支如下:

  • config-dev-main:开发主配置分支
  • config-prod-snapshot:生产配置镜像分支

同步规则:

  • Git -> PROD 只消费 config-dev-main
  • PROD -> Git 只写入 config-prod-snapshot

9.1 这样设计的价值

  • 避免生产回写内容再次触发下发
  • 生产快照不会污染开发主线
  • 便于审计“生产当前实际配置”

9.2 机器人提交标记

建议同步工具统一使用固定 commit message 前缀,例如:

sync(prod->git): traceId=xxx version=xxx

同时:

  • Git -> PROD 扫描时只关注 config-dev-main
  • 不读取 config-prod-snapshot

10. 状态库设计

新方案建议保留以下核心表:

10.1 sync_checkpoint

用于记录各方向最后一次成功同步的检查点。

关键字段:

  • direction
  • last_success_version
  • last_success_hash
  • updated_at

10.2 sync_task

用于记录每次同步任务生命周期。

关键字段:

  • trace_id
  • direction
  • source_version
  • content_hash
  • status
  • retry_count
  • error_msg

10.3 sync_ack

在新架构下:

  • 不再作为跨节点 ACK 使用
  • 已退出当前主 schema

如果后续需要审计扩展,可以单独恢复为接口调用日志表。

11. 幂等设计

建议继续使用以下组合作为幂等键:

direction + sourceVersion + contentHash

作用:

  • 同一开发版本不会重复推生产
  • 同一生产快照不会重复写 Git

12. 失败处理与补偿

12.1 自动重试

以下场景建议自动重试:

  • Git pull 失败
  • Git push 失败
  • 生产 push 接口调用失败
  • 生产 pull 接口调用失败

建议策略:

  • 最大重试次数:3 ~ 5
  • 指数退避:30s / 60s / 120s

12.2 失败落库

失败后建议:

  • 更新 sync_task.status=FAILED
  • 记录异常堆栈摘要
  • 增加重试次数
  • 保留最近一次成功检查点不变

12.3 人工补偿

后续可增加管理接口,支持:

  • traceId 重试
  • 按方向重跑最近一次失败任务
  • 查询最近同步记录

13. 安全设计

13.1 Git 访问建议

推荐使用:

  • HTTPS + Token

或:

  • SSH Deploy Key

13.2 权限建议

生产环境访问 Git 的账号建议采用最小权限原则:

  • config-dev-main 至少有读取权限
  • config-prod-snapshot 需要推送权限

更理想的做法:

  • 使用专用机器人账号
  • 对开发主分支启用保护
  • 限制机器人只写快照分支

13.3 生产接口认证

生产 push/pull 接口建议使用:

  • Bearer Token
  • HTTPS

14. 项目结构建议

新架构下建议进一步简化模块职责:

sync-tool
  |- src/main/java
  |   |- config
  |   |- git
  |   |- job
  |   |- repository
  |   |- service
  |   |- web
  |- src/main/resources
  |   |- application.properties
  |   |- application-prod-agent.properties

说明:

  • prod-agent 是唯一正式运行角色
  • dev-agent 与 FTP 相关模块已退出主运行面

15. 核心模块划分

建议保留并聚焦以下模块:

  • GitClientService
    • clone / pull / checkout / commit / push
  • ProdConfigApiService
    • 调用生产 push/pull 接口
  • SyncTaskService
    • 任务创建、状态变更、重试次数维护
  • CheckpointService
    • 成功检查点维护
  • ProdSyncCoordinator
    • 串联双向同步流程
  • JobScheduler
    • 定时调度

已退出主运行面:

  • FtpClientService
  • FTP 包上传下载逻辑
  • FTP ACK 逻辑

16. 定时任务建议

新架构下推荐保留两类核心任务:

16.1 GitToProdSyncJob

职责:

  • 拉取 config-dev-main
  • 判断是否有新 commit
  • 调用生产 push 接口

16.2 ProdToGitSnapshotJob

职责:

  • 调用生产 pull 接口
  • 判断是否有新快照
  • 提交到 config-prod-snapshot

可选任务:

  • RetryFailedTaskJob
  • HealthCheckJob

17. 一期 MVP 建议

建议重新按最小可交付版本收敛:

阶段 1打通 Git -> 生产

  • 生产环境直连开发 Git
  • 实现 config-dev-main 拉取
  • 实现生产 push 接口调用
  • 落库记录同步状态

阶段 2打通 生产 -> Git

  • 接入生产 pull 接口
  • 回写 config-prod-snapshot
  • 实现 commit + push

阶段 3增强稳定性

  • 补充重试
  • 补充管理接口
  • 补充告警与审计日志

18. 风险与注意事项

18.1 最大风险Git 写权限不足

如果生产环境对开发 Git 没有推送权限,则“生产 -> Git”链路无法完成。

解决方案:

  • 申请机器人账号
  • 或将“生产回写 Git”改成调用开发侧服务接口

18.2 最大风险:双向同步闭环

如果生产回写到了开发主分支,会再次触发下发。

规避措施:

  • 使用独立快照分支
  • 不扫描快照分支
  • 使用幂等键和机器人提交标记

18.3 最大风险:生产直连开发 Git 的安全边界

需要明确:

  • 网络访问是否合规
  • Git 账号权限是否受控
  • Token 或 SSH Key 是否可轮换

19. 结论

在“生产环境可以直接访问开发 GitFTP 不再需要”的前提下,推荐将旧方案调整为:

  • 生产环境单点部署
  • Git 直连
  • 保留生产 push/pull 接口
  • 保留 H2 状态库

这是比原来 FTP 中转更合适的方案,原因是:

  • 架构更简单
  • 故障点更少
  • 链路更短
  • 运维成本更低

20. 下一步建议

下一步建议按下面顺序推进:

  1. 先确认生产环境对开发 Git 是否具备推送权限
  2. 确认生产 push/pull 接口最终协议
  3. 在文件系统允许时物理删除退役占位类
  4. 将工程命名中残留的 ftp 语义继续清理
  5. 补充新的 application-prod-agent.properties 配置说明