backend-config-management-v2.md 7.0 KB

配置频繁变更场景下的后台管理方案

本文用于整理一套更适合“配置项变化很频繁”的后台方案。

适用前提:

  • 配置驱动型应用
  • 游戏规则和字段会持续变化
  • PostgreSQL 作为主数据库
  • Go 作为中间层
  • 客户端最终读取静态 JSON

核心目标是:

在保证后端稳定的前提下,让前端和玩法配置可以持续快速迭代。


1. 核心原则

这版方案的核心思想只有一句:

后端管理“容器、版本、引用、发布”,不要深度管理每个细字段。

也就是说:

  • 后端负责管理对象关系
  • 后端负责管理版本和发布
  • 后端负责做基础校验
  • 后端尽量不要写死每个玩法里的所有字段细节

2. 总体结构

推荐分成 3 层:

2.1 编辑层

后台管理系统面向的是“对象”,不是最终运行文件。

建议核心对象仍然是:

  • Map
  • Playfield
  • GameMode
  • ResourcePack
  • Event

2.2 装配层

Go 中间层负责:

  • 读取对象
  • 合并引用
  • 基础校验
  • 生成最终运行态配置

2.3 发布层

装配完成后,生成静态 JSON 上传到 OSS/CDN。

客户端只读取:

  • 已发布的静态配置

3. 数据库存什么

数据库建议只存两类数据:

3.1 稳定元信息

结构化列保存:

  • id
  • slug
  • name
  • status
  • current_version_id
  • created_at
  • updated_at

3.2 易变配置内容

使用 jsonb 保存:

  • content_jsonb

也就是说,每个对象都建议拆成:

  • 主表
  • version 表

例如:

  • maps / map_versions
  • playfields / playfield_versions
  • game_modes / game_mode_versions
  • resource_packs / resource_pack_versions
  • events / event_versions

这套结构最适合承接频繁变化的配置字段。


4. 为什么要用 version 表

配置频繁变化时,版本表非常重要:

  • 支持草稿
  • 支持当前版
  • 支持发布版
  • 支持历史回滚
  • 支持 diff
  • 支持审计

如果没有版本表,配置演进到后面会越来越难控。


5. 后端真正该负责的内容

后端建议强管理下面这 4 件事:

5.1 对象关系

例如:

  • Event 引用哪个 Map
  • Event 引用哪个 Playfield
  • Event 引用哪个 GameMode
  • Event 引用哪个 ResourcePack

5.2 版本机制

例如:

  • 草稿
  • 当前版本
  • 发布版本
  • 回滚历史

5.3 基础校验

只做真正稳定的校验:

  • 顶层结构是否合法
  • 引用是否存在
  • schemaVersion 是否兼容
  • 必填对象是否齐全

5.4 发布装配

把编辑态对象装配成最终运行态 JSON。


6. 后端不要过度负责的内容

后端不要把下面这些写死:

  • 每个玩法的小规则字段
  • 每个 HUD 开关
  • 每个实验性参数
  • 每个视觉细节配置
  • 每次快速迭代里新增的小配置项

这些变化太频繁,应该优先放在 jsonb 内容里,由前端消费。

一句话:

后端不要成为“所有细字段的业务解释器”。


7. 配置校验的推荐分层

建议分成 3 层校验。

7.1 通用结构校验

所有配置都校验:

  • schemaVersion
  • map
  • playfield
  • game

7.2 公共字段校验

只校验稳定公共字段,例如:

  • game.mode 必须存在
  • game.punch.radiusMeters > 0

7.3 玩法校验器

game.mode 分发,例如:

  • classic-sequential validator
  • score-o validator

但这里有个重要原则:

未识别字段默认允许透传。

也就是说:

  • 不要因为多了一个新字段就发布失败
  • 只有破坏基础结构或关键规则时才拦截

8. 后台编辑策略

后台不要追求“一开始把所有字段都做成完美表单”。

建议分成两类:

8.1 稳定字段

做正式表单:

  • 名称
  • 状态
  • 模式
  • 地图引用
  • Playfield 引用
  • 资源包引用
  • 关键半径
  • 是否必须起点/终点

8.2 易变字段

先保留模块化 JSON 编辑区:

  • game.sequence
  • game.guidance
  • game.visibility
  • game.feedback
  • playfield.controlOverrides
  • 其他试验性字段

等这些字段稳定后,再逐步升级成正式表单。

这会比一开始硬做全表单更现实。


9. 推荐的发布模型

建议增加一层:

  • event_releases

推荐字段:

  • id
  • event_id
  • event_version_id
  • release_no
  • manifest_url
  • published_by
  • published_at
  • status

发布流程:

  1. 后台选择某个 event_version
  2. Go 层装配最终配置
  3. Go 层校验
  4. 上传 OSS/CDN
  5. 写入 release 记录

客户端只消费:

  • 某次 release 对应的静态 JSON

10. Go 中间层的职责

Go 中间层建议承担 4 类职责:

10.1 装配器

负责把:

  • Map
  • Playfield
  • GameMode
  • ResourcePack
  • Event Overrides

装配成最终运行态配置。

10.2 校验器

负责:

  • 通用校验
  • 公共字段校验
  • 按玩法分发的插件式校验

10.3 发布器

负责:

  • 生成静态 JSON
  • 上传 OSS/CDN
  • 写入 release

10.4 预览 / Diff

负责:

  • 给后台看发布前的预览
  • 对比不同版本差异

一句话:

Go 中间层本质上是配置编译器,不只是 CRUD 服务。


11. 这套方案为什么适合当前项目

因为当前项目的真实情况就是:

  • 配置字段变化快
  • 玩法在持续演进
  • 前端经常需要新增规则项
  • 客户端更适合消费静态配置

如果后端每次都跟着细字段改表、改结构、改接口,成本会非常高。

这套方案可以避免:

  • 频繁 migration
  • 后端字段爆炸
  • 每次小字段变更都改很多 Go 代码

12. 推荐你现在就定死的原则

原则 1

数据库结构稳定,配置内容灵活。

原则 2

后端强管理对象关系,不强管理每个细字段。

原则 3

未知字段默认允许透传。

原则 4

客户端消费细规则,后端负责发布与校验。

原则 5

最终运行态永远是静态 JSON。


13. 和当前目录结构的关系

如果当前静态目录是:

  • map/
  • kml/
  • event/

这套可以继续保留。

理解方式是:

  • 数据库 = 编辑态
  • Go 装配 = 发布态转换
  • OSS 目录 = 运行态产物

也就是说后台发布后,继续生成:

  • event/classic-sequential.json
  • event/score-o.json
  • map/...
  • kml/...

客户端现有读取逻辑无需推翻。


14. 推荐实施顺序

建议按下面顺序推进:

第一步

先建 5 个核心对象:

  • Map
  • Playfield
  • GameMode
  • ResourcePack
  • Event

第二步

为每个对象补 version 表。

第三步

Go 中间层先做最小装配功能。

第四步

实现发布到 OSS/CDN。

第五步

后台逐步把稳定字段表单化。

第六步

把易变字段继续保留为 JSON 编辑区。


15. 一句话总结

这套更适合频繁变化配置项的后台方案是:

PostgreSQL 存“版本化对象 + jsonb 内容”,Go 中间层做“装配 + 校验 + 发布”,客户端只读静态发布结果。