# PAR Server 接口升级对比文档 (供 MediaBot 迁移) > **版本**: V2.0(SiteSnapshot 重构) > **日期**: 2026-07-07 > **面向对象**: MediaBot 开发团队 --- ## 一、升级概览 本次重构将站点配置的存储和分发方式从 **"分散存储 + 运行时合并"** 升级为 **"统一快照 + 增量更新"**。核心变化: | 维度 | 旧方案 (V1) | 新方案 (V2) | |------|------------|------------| | **存储** | 脚本/页面/规则分别存七牛云 | MySQL `site_snapshots` 表统一存储 + 七牛云 CDN 灾备 | | **获取方式** | 多次请求分别获取脚本、页面、规则 | **一次请求获取完整 bundle** | | **更新检测** | 无/各接口各自判断 | **统一 checksum + ETag/304** 增量更新 | | **可用性** | 依赖七牛云 | 数据库为主 + 七牛云 CDN 自动灾备 | --- ## 二、新增接口(推荐 MediaBot 迁移到这些) ### 2.1 `GET /api/v1/snapshots/{siteId}` ⭐ 推荐 **用途**: 获取站点完整配置快照(一站式获取脚本 + 页面配置 + 风险规则) **请求头**: ``` If-None-Match: {上次返回的 ETag checksum} ``` **响应 200 OK**(内容未变化时): ```json { "siteId": "example.com", "generatedAt": "2026-07-07T10:30:00", "script": "// Groovy 脚本完整源码...", "scriptVersion": "3", "scriptSource": "custom", "pages": [ { "pageKey": "INDEX", "url": "https://example.com/torrents.php", "method": "GET", "...": "..." } ], "pagesVersion": "2", "pagesSource": "custom", "riskRules": [ { "field": "title", "operator": "contains", "value": "xxx", "level": "WARN" } ], "riskRulesVersion": 1 } ``` **响应 304 Not Modified**(内容未变化): ``` HTTP/1.1 304 Not Modified ETag: "abc123def456..." ``` _(Body 为空,节省带宽)_ **可用性保障**: - 优先从 MySQL 数据库读取 - 数据库不可用时自动回退到七牛云 CDN `snapshots/{siteId}.json` - 两层级联失败返回 500 --- ### 2.2 `GET /api/v1/snapshots/{siteId}/check` ⭐ 推荐 **用途**: 轻量级检查站点是否有配置更新(不传输配置内容) **响应**: ```json { "code": 200, "data": { "checksum": "abc123def456...", "version": 5, "publishedAt": "2026-07-07T10:30:00" } } ``` **使用模式**: 1. MediaBot 先调 `/check` 获取最新 `checksum` 2. 与本地缓存的 checksum 比较 3. 不同时再调 `/snapshots/{siteId}` 拉取完整配置 --- ## 三、旧接口兼容状态 以下接口**继续可用**,但推荐逐步迁移到新接口: ### 3.1 `GET /api/v1/configs/{siteId}/bundle` — ⚠️ 保持兼容 | 项目 | 说明 | |------|------| | **状态** | 继续可用,底层已委托给快照服务 | | **变化** | 无破坏性变化,响应格式不变 | | **建议** | 可继续使用,但建议迁移到 `GET /api/v1/snapshots/{siteId}` | **数据流变化**: ``` 旧: 七牛云 bundles/{siteId}.json → 返回 新: MySQL site_snapshots → 返回 (优先) ↓ 失败 七牛云 bundles/{siteId}.json / snapshots/{siteId}.json → 返回 (回退) ↓ 失败 实时构建 → 返回 (兜底) ``` ### 3.2 `GET /api/v1/configs/{siteId}/script` — ⚠️ 保持兼容 | 项目 | 说明 | |------|------| | **状态** | 无变化,功能一致 | | **建议** | 如需单独获取脚本,可继续使用;否则建议用 snapshot 一次性获取 | ### 3.3 `GET /api/v1/scripts/{siteId}` — ⚠️ 保持兼容 | 项目 | 说明 | |------|------| | **状态** | 无变化,功能一致 | | **说明** | 仅返回 Groovy 脚本纯文本,无 JSON 包装 | | **建议** | 如需单独获取脚本,可继续使用 | ### 3.4 `GET /api/v1/scripts/{siteId}/version` — ⚠️ 保持兼容 | 项目 | 说明 | |------|------| | **状态** | 无变化 | | **响应** | `{ "version": "3", "source": "custom" }` | | **建议** | 可用 `/snapshots/{siteId}/check` 替代,后者提供更全面的版本信息 | ### 3.5 `GET /api/v1/manifest` — ⚠️ 保持兼容 | 项目 | 说明 | |------|------| | **状态** | 无变化,仍支持 ETag | | **说明** | 返回所有活跃站点配置索引(siteId、站点类型、是否有脚本/页面/规则等元信息) | | **建议** | 继续用于获取全量站点列表和配置状态概览 | ### 3.6 `GET /api/v1/sites/{siteId}/pages` — ⚠️ 保持兼容 | 项目 | 说明 | |------|------| | **状态** | 无变化 | | **建议** | 如只需页面配置,可继续使用;否则建议用 snapshot | ### 3.7 `GET /api/v1/risk-rules/{siteType}` — ⚠️ 保持兼容 | 项目 | 说明 | |------|------| | **状态** | 无变化,仍支持版本号增量判断 | | **建议** | 如只需风险规则,可继续使用;否则建议用 snapshot | --- ## 四、推荐 MediaBot 迁移方案 ### 方案 A:完全迁移到 Snapshot(推荐) ``` MediaBot 启动 / 定时任务: 1. GET /api/v1/manifest → 获取全量站点列表 2. 对每个站点: a. GET /api/v1/snapshots/{siteId}/check → 获取最新 checksum b. 与本地缓存的 checksum 比较 c. 不同时: GET /api/v1/snapshots/{siteId} → 拉取完整 bundle d. 缓存 checksum 和完整 bundle ``` **优点**: - 每次只需 1~2 次 HTTP 请求即可获取站点全部配置 - ETag/304 支持,配置未变时不传输内容 - 三层可用性保障(数据库 → CDN → 实时构建) ### 方案 B:渐进式迁移(兼容期) ``` 1. 优先调用新接口 GET /api/v1/snapshots/{siteId} 2. 失败时 fallback 到旧接口组合: - GET /api/v1/configs/{siteId}/script - GET /api/v1/sites/{siteId}/pages - GET /api/v1/risk-rules/{siteType} ``` --- ## 五、响应格式对比 ### 旧方式(分散获取) 需要 **3~4 次 HTTP 请求** 才能凑齐一个站点的完整配置: ``` 请求 1: GET /api/v1/configs/{siteId}/script → 返回 Groovy 脚本纯文本 请求 2: GET /api/v1/sites/{siteId}/pages → 返回页面入口配置 请求 3: GET /api/v1/risk-rules/{siteType} → 返回风险规则 请求 4: (可选) GET /api/v1/manifest → 返回全局站点列表 ``` ### 新方式(统一快照) **1~2 次 HTTP 请求** 获取站点完整配置: ``` 请求 1: GET /api/v1/snapshots/{siteId} (带 If-None-Match) → 返回完整 bundle - 配置未变化: 304 Not Modified (0 流量) - 配置有变化: 200 OK + 完整 JSON (可选) 请求 0: GET /api/v1/manifest → 获取全量站点列表 ``` ### Bundle JSON 响应字段说明 | 字段 | 类型 | 说明 | |------|------|------| | `siteId` | string | 站点标识 | | `generatedAt` | string | 快照生成时间 (ISO 8601) | | `script` | string | Groovy 脚本完整源码 | | `scriptVersion` | string | 脚本版本号 | | `scriptSource` | string | `"custom"` 或 `"default"` | | `pages` | array | 页面入口配置条目列表 | | `pagesVersion` | string | 页面配置版本号 | | `pagesSource` | string | `"custom"` 或 `"default"` | | `riskRules` | array | 风险规则列表 | | `riskRulesVersion` | integer | 风险规则版本号 | --- ## 六、鉴权说明 **无变化**。所有配置读取接口(snapshot、manifest、script、pages、risk-rules)均为**公开接口**,无需鉴权。提交类接口需 HMAC/PSK 或 JWT 认证。 --- ## 七、迁移时间线建议 | 阶段 | 时间 | 操作 | |------|------|------| | **Phase 1** | 立即 | MediaBot 开始调用 `/snapshots/{siteId}` 作为主路径,旧接口作为 fallback | | **Phase 2** | 稳定运行 2 周后 | 移除旧接口 fallback 逻辑 | | **Phase 3** | 后续版本 | 视情况废弃分散获取接口(script/pages/rules 独立端点) | --- ## 八、FAQ **Q: 旧接口会下线吗?** A: 短期内不会。但建议尽快迁移到 snapshot 接口以获得更好的性能和可用性。 **Q: snapshot 接口响应时间会不会更长?** A: 不会。数据库查询是单次 SQL(按 site_id + status 索引),且应用层有 Caffeine 缓存。304 场景下完全不传输内容。 **Q: 如果 PAR Server 完全挂了怎么办?** A: Snapshot 在发布时会同步上传到七牛云 CDN (`snapshots/{siteId}.json`),MediaBot 可以直接从 CDN 读取作为终极灾备。 **Q: checksum 是用什么算法计算的?** A: SHA-256,对完整 bundle JSON 内容计算。 **Q: bundle 和 snapshot 的区别?** A: 同一份数据。`/configs/{siteId}/bundle` 是兼容旧路径,`/snapshots/{siteId}` 是新路径,底层数据源相同。