diff --git a/PLAN.md b/PLAN.md index 563ab41..ac44d56 100644 --- a/PLAN.md +++ b/PLAN.md @@ -123,6 +123,74 @@ - 风险:CDN 缓存导致短时间读取旧配置(通过短缓存 + 原子发布缓解)。 - 回滚:将 A/B 两端 `active` 同步改回原服务器,并设置 `cooldownMinutes=0` 可快速恢复。 +### 0.10 非付费负载均衡预案(Cloudflare Workers,暂不实施) + +目标: +- 在不使用 Cloudflare Load Balancer 付费能力的前提下,实现 A/B 两端流量分发与故障回退。 +- 小程序侧统一使用单一入口域名,减少合法域名和切换复杂度。 + +建议架构: +1. 新增统一入口域名(示例:`mp-api.biboer.cn`),仅小程序访问该域名。 +2. 入口域名绑定 Cloudflare Worker 路由(`mp-api.biboer.cn/*`)。 +3. Worker 负责: +- `/api/*` 按权重分流到 A/B(初始建议 A:90%,B:10%)。 +- 主节点失败时自动重试备用节点(一次重试即可)。 +- `GET/HEAD` 以外请求复用同一请求体,避免重试时 body 丢失。 +4. 静态配置与字体资源在首阶段固定走 A(`fonts.biboer.cn`),避免 A/B 字体清单不一致引起渲染差异。 + +权重修改与热加载(推荐): +1. 不将权重硬编码在 Worker 代码中,避免每次改权重都重新发布。 +2. 新增独立配置文件(示例:`/miniprogram/assets/lb-config.json`),由 Worker 定期拉取。 +3. Worker 本地缓存最近一次有效配置,按 TTL(建议 30~60 秒)自动刷新。 +4. 权重调整流程仅需改配置文件并发布配置,无需小程序发版、无需 Worker 重新部署。 + +`lb-config.json` 建议结构: + +```json +{ + "weights": { + "A": 90, + "B": 10 + }, + "ttlSeconds": 60, + "minSwitchIntervalSeconds": 30 +} +``` + +字段约束: +- `weights.A`、`weights.B`:`0~100`,且总和必须为 `100`。 +- `ttlSeconds`:Worker 重新拉取配置间隔,建议 `30~60`。 +- `minSwitchIntervalSeconds`:最小切换间隔,避免流量来回抖动。 + +前置条件(实施前必须满足): +1. A/B 字体文件与清单一致(当前 `fontCount` 必须对齐)。 +2. A/B API 行为一致:`/healthz`、`/api/render-svg`、`/api/render-png`。 +3. 小程序后台已配置统一入口域名为合法 `request/downloadFile` 域名。 + +分阶段实施: +1. P0(演练) +- 先用 Worker 做单域名透传(100% A),验证链路稳定性。 +2. P1(灰度) +- 开启 `/api/*` 90/10 分流,观察失败率与时延(至少 24 小时)。 +3. P2(增配) +- 视稳定性逐步调整 80/20、70/30,不直接跳 50/50。 +4. P3(稳态) +- 形成标准运维流程:权重调整、紧急回切、日志巡检。 + +回滚策略: +1. Worker 立即切为 100% A。 +2. 若 Worker 故障,DNS/路由回退到 A 直连入口。 +3. 保留 `route-config` 手动切换机制作为最终兜底,不删除。 + +配置容错(实施时必须包含): +1. 配置拉取失败:继续使用“上一次有效配置”,不回退空配置。 +2. 配置格式非法:记录错误并忽略本次配置,继续使用旧配置。 +3. 连续失败超过阈值:自动降级到 `A=100, B=0`,并输出告警日志。 + +暂不实施说明: +- 本节仅记录方案和执行顺序,当前版本继续使用“手动 A/B 切换”主路径。 +- 待 A/B 数据一致性、日志与监控项完善后,再启动该预案实施。 + ## 1. 当前状态 ### 1.1 已完成(保留能力) diff --git a/README.md b/README.md index 316d8c9..23e2588 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,13 @@ - 小程序渲染服务(`apiserver/`):服务端渲染 SVG API - Python CLI(根目录脚本):图片转 SVG、字体文本转 SVG +## 最新版本 + +- `v1.0.3`(2026-02-10) +- 小程序新增“手动路由切换”能力:通过远端 `route-config.json` 在 A/B 服务间切换,无需小程序发版 +- 切换策略包含双确认与 `cooldown` 防抖,降低误切换与来回抖动 +- B 侧新增 Cloudflare Tunnel 接入路径(`mac-tunnel.biboer.cn`),适配家庭网络场景 + ## 文档导航 - 项目总览:`README.md` diff --git a/release.md b/release.md index b11ad1b..c666d08 100644 --- a/release.md +++ b/release.md @@ -1,5 +1,48 @@ # Release Notes +## v1.0.3 +发布时间:2026年2月10日 +版本定位:小程序远端路由切换与多节点接入增强 + +### 里程碑与亮点 + +- 新增小程序“无发版切换后端”能力(基于远端 `route-config.json`) +- 引入双确认切换策略,避免单点误配置导致错误跳转 +- 增加 `cooldown` 防抖,防止 A/B 来回抖动 +- 新增 Cloudflare Tunnel 入口域名支持(`mac-tunnel.biboer.cn`) + +### 核心变更 + +#### 小程序路由管理 +- 新增 `route-manager`,负责: + - 启动时读取路由配置 + - 回前台按节流规则检查路由 + - 接口失败时触发兜底路由检查 +- 路由状态本地持久化:`activeServerKey`、`lastSwitchAt`、`routeConfigCache`、`lastRouteCheckAt` + +#### 切换规则 +- 双确认:当前服务读取到目标为 `B` 时,必须继续读取 `B` 的配置并确认 `active=B` 才切换 +- 防抖:`cooldownMinutes` 控制最短驻留时间,`0` 表示允许立即切换 +- 读取失败保护:目标配置读取失败或非法时保持当前服务不变 + +#### 接入与运维 +- 新增 `miniprogram/assets/route-config.json` 配置模板 +- `scripts/deploy-fonts.sh` 支持同步 `route-config.json` +- `miniprogram/README.md`、`apiserver/README.md` 同步更新 +- mac 侧新增 Tunnel 接入路径,支持 `mac-tunnel.biboer.cn` 对外服务 + +### 配置注意事项 + +- 小程序后台必须将目标域名加入 `request` 与 `downloadFile` 合法域名 +- `route-config.json` 修改后建议清除本地 `route-state` 并冷启动验证 +- `/healthz` 建议使用 `GET` 校验(`HEAD` 可能返回 `501`) + +### 验收项 + +- 可通过修改远端 `route-config.json` 在 A/B 节点间切换,无需重新发布小程序 +- A/B 配置不一致时不切换(保护行为) +- 目标节点不可用时不切换(保护行为) + ## v1.0.1 发布时间:2026年2月9日 版本定位:小程序 UI 优化与布局完善 @@ -89,4 +132,3 @@ miniprogram/ - 邮箱:douboer@gmail.com - 仓库:Issues -