配置同步与发布链路
ApiGo 的接口配置不会直接作用于线上流量。一条接口从「设计态」变成「可调用」需要经过:保存接口定义 → 生成开发环境发布快照 → 同步到目标环境 → 写入 Redis 运行态 → 通知网关刷新。 本文说明这条链路上的数据流转、缓存结构和失败兜底。
设计态与运行态
| 状态 | 存储位置 | 内容 | 谁在读 |
|---|---|---|---|
| 设计态 | MySQL base_api_info | 接口的完整定义:SQL/代理配置、参数、插件、分组 | 管理端编辑页 |
| 发布态 | MySQL base_api_release | 某一环境、某一修订号下的不可变快照 | 发布管理、运行态构建 |
| 运行态 | Redis | 路由定义、接口详情、限流/熔断/缓存/IP 规则、应用密钥、订阅状态 | 网关、执行服务 |
设计态修改不会影响已发布接口。只有执行「发布」或「同步」后,修改才会进入快照并同步到运行态。
发布快照模型
关键字段
| 字段 | 含义 |
|---|---|
sourceApiId | 快照来源的设计态接口 ID;同一接口的所有环境快照共享该值 |
apiLinkId | 版本族 ID。接口被复制/迁移后仍可追溯到同一族,用于计算修订号 |
envCode | 环境编码,dev 为开发 环境,其余为自定义环境 |
deployRevision | 修订号,同一 apiLinkId 内单调递增;跨环境比较修订号即可判断是否需要同步 |
isCurrent | 该环境当前生效的快照;同一接口同一环境只允许一条为 1 |
apiPath | 已拼接环境前缀的实际访问路径 |
enabled | 上线/下线状态,同步时从设计态带过来 |
发布动作
- 发布到开发环境:每次发布都锁定版本族根节点、计算新修订号、生成新快照,并把旧快照
isCurrent置 0。 - 同步到目标环境:比较目标环境当前快照的
deployRevision与开发环境当前修订号。- 相同:直接返回,不重复生成快照。
- 目标环境已存在同修订号快照:复用该快照并切换为当前版本。
- 否则:以开发环境快照为模板生成目标环境快照,重新拼接目标环境路径前缀。
- 回滚:把目标环境某条历史快照重新置为
isCurrent=1,并刷新运行态。 - 删除环境版本:删除目标环境快照并刷新运行态;开发环境版本不允许单独删除,需删除源接口。
开发环境快照代表「最新可运行版本」。同步目标环境时,系统会先确保开发环境存在当前快照,再以它为模板。因此没有发布过的接口无法同步到其他环境。
运行态构建
管理端 ApiRuntimeCacheService 负责把发布快照转换为运行态数据:
路由定义
路由写入 Spring Cloud Gateway 原生 Redis 路由仓库,Key 为 routedefinition_<routeId>:
routeId优先取发布快照中配置的路由 ID;没有则取接口 ID;再没有则生成 UUID。- 断言固定为
Path + Method,避免同路径不同方法互相覆盖。 - 上游地址为
lb://<服务名>(微服务模式)或配置的执行服务地址。 - 超时、重试等参数来自接口定义与全局配置。
规则存储
| 规则 | Redis 结构 | 维度 |
|---|---|---|
| 流控 | Hash crabc_flow_rule | Gateway routeId |
| 熔断 | Hash crabc_degrade_rule | Gateway routeId |
| 接口缓存 | Hash crabc_api_cache | 接口 / 路由 |
| IP 规则 | Hash | 接口详情维度 |
流控与熔断规则以路由 ID 为 Hash field,而不是接口 ID。原因是一个接口在不同环境、不同发布路径下可能对应多条路由,按路由维度下发才能保证规则精确命中。
变更通知机制
事件结构
管理端每次修改运行态数据后,通过 Redis Pub/Sub 发布 CacheChangeEvent:
| 字段 | 说明 |
|---|---|
resourceType | 资源域:ROUTE、API_DETAIL、FLOW_RULE、DEGRADE_RULE、CACHE_RULE、IP_RULE、APP_KEY、SUBSCRIPTION、DATASOURCE、SKILL_DETAIL |
changeAction | UPSERT / DELETE / REFRESH |
version | 资源域版本号,发布时自增 |
resourceIds | 受影响的资源 ID,REFRESH 时为空表示全量 |
source | 事件来源,便于排查 |
频道为 crabc_change_notify,版本号 Key 为 crabc_change_version:<resourceType>。
网关处理
RedisMessageListener 按资源域分发:
| 事件 | 网关动作 |
|---|---|
ROUTE | 发布 RefreshRoutesEvent,重新读取 Redis 路由 |
FLOW_RULE / DEGRADE_RULE | 增量更新本地规则快照,调用 Sentinel loadRules |
API_DETAIL / CACHE_RULE / IP_RULE | 清理接口详情缓存;带 ID 时只失效对应接口,REFRESH 时全量清理 |
APP_KEY | 清理应用与工具列表缓存 |
SUBSCRIPTION | 清理订阅运行态缓存 |
顺序与幂等
事件携带版本号,网关记录每个资源域最近处理的版本:
- 版本号小于等于已处理版本的事件会被丢弃,防止网络重投或乱序导致旧数据覆盖新状态。
- 增量事件按
resourceIds精确失效,避免无关接口缓存被清空。 REFRESH语义用于全量重建,不依赖具体 ID。
失败兜底
Pub/Sub 是「至多一次」语义,网络抖动可能丢消息。系统提供两层兜底:
- 定时版本对账:网关每 5 分钟读取各资源域最新版本号,与本地已处理版本比较;发现落后时重新订阅频道并按
REFRESH重建。 - 手动对账:管理端
ManualReconcileService可对API_DETAIL、ROUTE、FLOW_RULE、DEGRADE_RULE、CACHE_RULE、IP_RULE补发REFRESH事件,用于发布后异常排查。
正常情况下变更在秒级生效。若出现「已发布但仍提示接口不存在」,先确认网关日志是否收到变更事件,再执行手动对账;仍不生效时检查 Redis 中是否存在对应 routedefinition_* Key。
数据源同步
数据源的同步策略与接口不同:
- 管理端把数据源配置(密码加密存储)写入 Redis 快照
crabc_data_source,并维护快照时间戳字段。 - 快照使用原子替换,避免管理端多实例并发刷新时读到半份数据。
- 每个 Admin 实例各自维护本地连接池;配置未变化不重建连接池,密码轮转等变更会触发重建。
- 数据源变更发布
DATASOURCE事件,执行服务清理本地数据源缓存后按需重新获取。
与许可证的关系
License 校验独立于配置同步:启动时 LicenseStartupRunner 校验失败会直接阻断进程启动;运行期间每 24 小时定时校验,失效则优雅退出(退出码 1)。License 不参与路由与规则下发。详见 部署拓扑与 License。