Verification: Focused tests InterfaceFailoverPolicyTest/StateTest/OrderStoreTest/BackupPreferenceFilterTest passed; Mobile and Leanback Arm64 javac passed; git diff --check passed Task-Guard: failover-default-auto-review-20260914
11 KiB
接口容灾设计
1. 目标
为点播接口增加统一的容灾机制。当用户当前使用的接口无法正常拉取数据或加载失败时,系统按用户配置的接口顺序切换到下一个可用接口。
本设计只覆盖“点播接口配置加载失败”场景,不覆盖以下场景:
- 站点首页、详情、搜索失败
- 站点播放地址解析失败
- 播放器内核切换、解码切换
- 直播接口、壁纸接口
- 换源容灾
2. 三种模式
| 模式 | 默认 | 行为 |
|---|---|---|
| 关闭 | 是 | 当前接口失败后仅提示错误,不自动切换 |
| 自动容灾 | 否 | 当前接口失败后按顺序自动尝试下一个未尝试接口 |
| 手动确认 | 否 | 当前接口失败后弹出确认框,由用户决定是否切换到下一个或指定接口 |
三种模式互斥,同一时刻只生效一种。
2.1 关闭
行为完全保持现状:
- 用户配置或手动选择某个点播接口。
- 加载失败。
- 弹出错误提示。
- 不切换接口,不发起额外请求。
关闭模式是安全回退锚点。实现后如果发现任何自动切换副作用,应优先回退到关闭模式。
2.2 自动容灾
- 用户配置或手动选择某个点播接口。
- 加载失败。
- 系统从用户排序后的接口序列中,找到当前接口之后的下一个未尝试接口。
- 自动加载该接口。
- 加载成功则走正常成功链路。
- 全部候选接口都已失败后,弹出最终错误提示。
自动容灾不需要用户参与。每次切换应显示当前尝试的接口名或地址,避免用户误以为仍在加载原接口。
2.3 手动确认
- 用户配置或手动选择某个点播接口。
- 加载失败。
- 弹出确认框,列出剩余未尝试接口。
- 用户可选:
- 切换到下一个接口
- 指定切换到某个接口
- 取消切换
- 用户确认后才发起下一次加载。
- 用户取消后不再继续本轮容灾。
手动确认模式只在加载失败后弹出一次确认框。若用户选择切换后再次失败,可以继续弹出下一次确认框,或维持单次确认后结束本轮;推荐后者,避免连续弹窗打扰。
3. 接口序列与排序
3.1 排序来源
接口容灾顺序来自用户手动排序的接口序列。若用户没有自定义顺序,则按当前数据库默认顺序。
当前默认顺序:
SELECT * FROM Config WHERE type = 0 ORDER BY time DESC
新增手动排序后,不修改数据库结构,不引入数据库 migration。排序持久化到应用偏好存储,键按点播接口类型作用域隔离。
3.2 存储键
建议新增:
interface_order_vod
值格式:
[
"https://example.com/config-a.json",
"https://example.com/config-b.json",
"https://example.com/config-c.json"
]
按接口 URL 唯一标识。重复 URL 只保留一次。
3.3 排序规则
- 取当前点播接口集合。
- 按用户排序键重排。
- 用户排序中不存在的接口追加到末尾。
- 已删除接口的排序键保留在偏好存储中但不参与排序。
- 新增接口默认追加到末尾。
3.4 排序入口
建议在现有接口历史弹层中增加排序入口:
- 手动拖拽调整顺序
- 排序后立即保存
- 当前接口也参与排序
- 当前接口保持可见,不因“当前使用中”而剔除
这样可以保证用户看到完整容灾顺序,而不是只见“其他接口”的局部顺序。
4. 失败判定
仅以下情况触发接口容灾:
- 配置 URL 请求失败。
- HTTP 状态异常。
- JSON 解析失败。
- 配置返回
msg字段。 - 配置解析出的
sites为空。 - 配置仓库
urls解析结果为空。
以下情况不触发接口容灾:
- 接口加载成功,但首页无内容。
- 接口加载成功,但详情或搜索失败。
- 接口加载成功,但播放地址解析失败。
- 接口加载成功,但播放器内核或解码失败。
- 用户主动取消加载。
- 更高优先级的加载请求已使当前请求失效。
4.1 不做播放链路容灾
接口加载成功后,首页、详情、搜索、播放链路失败应继续由现有站点健康排序、播放器内核容灾、换源机制处理。接口容灾不应接管这些场景,否则会把“配置不可用”与“站点不可用”混淆,带来更大副作用。
5. 自动容灾流程
5.1 状态
本轮容灾只维护一次状态:
failoverRoundId
originUrl
attemptedUrls
candidateUrls
currentIndex
5.2 步骤
- 记录本轮
failoverRoundId。 - 构造候选接口序列:
InterfaceOrderStore.sortConfigs(Config.getAll(0))。 - 将当前接口 URL 加入
attemptedUrls。 - 从
currentIndex开始向后查找第一个未尝试接口。 - 加载该接口。
- 若失败,重复步骤 4。
- 若成功,走正常成功链路。
- 若没有更多未尝试接口,走最终失败链路。
5.3 防重复
- 同一轮内按 URL 去重。
- 已失败接口不再重试。
- 新一轮容灾必须重置状态。
- 用户手动选择接口应开启新一轮,而不是沿用上一轮状态。
- 同一轮内避免环形死循环。
5.4 尝试上限
为防呆,建议同轮最多尝试:
min(candidateCount, 3)
如果用户明确需要更多候选,可以后续再调大。第一版保守上限有助于控制请求和提示成本。
6. 手动确认流程
6.1 弹框内容
- 标题:接口加载失败
- 副标题:当前接口名称或地址
- 剩余候选接口列表
- 操作:
- 切换到下一个
- 指定接口
- 取消
如果剩余候选接口只有一个,可将“指定接口”简化为“切换到该接口”。
6.2 交互
- 失败后弹出一次。
- 用户选择“切换到下一个”后,加载下一个候选接口。
- 若再次失败,结束本轮,不再继续弹窗。
- 用户选择“指定接口”时,先展示剩余候选接口列表,再由用户选择一个。
- 用户选择“取消”后,结束本轮。
6.3 状态
手动确认与自动容灾共享同一个候选序列构造逻辑,但增加一个用户决策等待点。若用户取消或未决策,不继续发起请求。
7. 提示
7.1 自动容灾提示
- 切换时显示“正在尝试下一个接口”。
- 尽量带出接口名称或地址。
- 多次连续切换时避免频繁刷新同一个 Toast。
- 全部失败后显示最终错误。
7.2 手动确认提示
- 失败后立即弹出确认框。
- 确认框需要能看到当前失败接口和剩余候选接口。
- 用户取消后显示“已取消接口切换”。
7.3 关闭模式提示
- 只显示当前加载失败的原始错误。
- 不显示“已尝试 N 个接口”。
- 不显示任何切换提示。
8. 成功与失败链路
8.1 成功
- 接口加载成功。
- 更新当前接口。
- 触发现有配置成功事件。
- 触发现有首页、站点、解析器、规则等消费方刷新。
- 若来自容灾,通知可带出“已切换到 xxx”。
8.2 失败
- 所有候选接口都已失败。
- 只回调一次最终错误。
- 不发中间配置事件。
- 不触发首页、详情、播放器中间刷新。
- 保持当前失败前的界面状态。
8.3 中间失败不发事件
自动容灾过程中,每次中间失败都不应触发 ConfigEvent.vod()。只有最终成功或最终失败后才发一次事件,避免首页或播放页反复刷新。
9. 实现位置
9.1 建议集中点
VodConfigBaseConfig
理由:
- 接口加载集中在这两层。
- 成功/失败回调集中。
- UI 只需要在最终回调中处理提示。
- 不需要每个入口各自实现 fallback。
9.2 不建议的位置
VodFragmentHomeActivitySettingFragment- 各 UI 回调
这些位置只能处理最终提示,不应承载容灾状态机。否则手机端、TV 端、远程接口、配置仓库等入口会出现重复实现和行为不一致。
10. 设置存储
10.1 设置键
建议新增:
interface_failover_mode
值:
0 = 关闭
1 = 自动容灾
2 = 手动确认
10.2 默认值
默认值应为 1,即自动容灾。
10.3 设置入口
建议放在增强设置页,归类为“接口容灾”或“接口韧性”。
10.4 备份与同步
设置键和接口排序键应纳入备份与一键同步,保证用户换机后容灾顺序和模式不丢失。
11. 回退路径
11.1 运行时回退
- 用户把模式切回“关闭”。
- 立即停止当前容灾轮次。
- 不发起新的候选接口请求。
11.2 实现回退
如果上线后发现严重副作用,应优先回退到关闭模式默认值,而不是直接移除排序或设置项。
11.3 代码回退
如果必须回退代码,应保留排序存储结构和设置键,避免用户数据丢失。
12. 验证
12.1 单元测试
建议至少覆盖:
- 接口排序保存、恢复、去重。
- 新增接口追加到末尾。
- 已删除接口不参与排序。
- 关闭模式不触发容灾。
- 自动容灾失败后尝试下一个未尝试接口。
- 自动容灾全部失败后只回调一次最终错误。
- 自动容灾同轮内不重复尝试同一接口。
- 自动容灾同轮内尝试次数不超过上限。
- 手动确认用户取消后不继续请求。
- 手动确认用户切换后只尝试一次。
- 中间失败不发
ConfigEvent.vod()。 - 成功后走正常成功链路。
- 设置键纳入备份。
- 排序键纳入备份。
12.2 手动验证
- 设置页切换三种模式。
- 关闭模式:接口失败后仅提示,无切换。
- 自动容灾:接口失败后自动切换到下一个接口。
- 自动容灾:所有接口失败后显示最终错误。
- 手动确认:接口失败后弹出确认框。
- 手动确认:用户取消后不切换。
- 手动确认:用户确认后切换到指定或下一个接口。
- 接口排序调整后,容灾顺序随之变化。
- 容灾成功后首页、站点、解析器、规则正常刷新。
- 容灾过程中不出现首页或播放页重复刷新。
12.3 回归边界
以下能力不应受本设计影响:
- 站点健康排序
- 换源
- 播放器内核自动切换
- 解码自动切换
- 直播接口
- 壁纸接口
- 配置仓库导入
13. 边界与不做事项
- 不合并所有接口的全局配置。
- 不把多个接口的
sites/parses/rules/headers/proxy/webHomeExtensions合并成一个虚拟配置。 - 不对站点首页、详情、搜索、播放失败做接口级切换。
- 不修改
Config数据库实体。 - 不引入数据库 migration。
- 不将接口容灾与“聚合全部接口”混为同一开关。
- 默认开启自动容灾;用户可随时切换为关闭或手动确认。
- 不在关闭模式下发起额外请求。
- 不在中间失败后触发全局事件。