- 移除 SiteSnapshotServiceImpl 对 ConfigService 的依赖,直接使用 SiteConfigMapper - ConfigServiceImpl/SitePagesServiceImpl/RiskRuleServiceImpl 改用 ApplicationEvent 异步触发快照更新 - 新增 SnapshotUpdateEvent 和 SnapshotUpdateListener - ParApplication 添加 @EnableAsync 支持异步事件处理 - AdminController 中 updateSnapshot 调用改为发布事件
8.5 KiB
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(内容未变化时):
{
"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 ⭐ 推荐
用途: 轻量级检查站点是否有配置更新(不传输配置内容)
响应:
{
"code": 200,
"data": {
"checksum": "abc123def456...",
"version": 5,
"publishedAt": "2026-07-07T10:30:00"
}
}
使用模式:
- MediaBot 先调
/check获取最新checksum - 与本地缓存的 checksum 比较
- 不同时再调
/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} 是新路径,底层数据源相同。