Appearance
整体架构
架构图
┌──────────────────────────────────────────────────────────┐
│ 底层配置服务 │
│ GET /sdk/getAvailableDomainList │
│ 返回:{"code":0,"data":"<AES-256-GCM 密文>","msg":"success"} │
└────────────────────────────┬─────────────────────────────┘
│ 定时拉取(建议每 10 分钟)
│ 拉取失败时沿用上次缓存
▼
┌──────────────────────────────────────────────────────────┐
│ 业务服务端 │
│ │
│ • 定时拉取并缓存密文 data │
│ • 不解密,直接存储密文 │
│ • 提供自有接口给客户端(GET /your-api/sdk-config) │
│ • 返回密文 data 给客户端 │
└────────────┬──────────────────────────────┬─────────────┘
│ App 启动时请求 │ 页面加载时请求
▼ ▼
┌────────────────────┐ ┌────────────────────────┐
│ Flutter App │ │ Web 页面 │
│ │ │ │
│ 获取密文 data │ │ 获取密文 data │
│ 传入 Flutter SDK │ │ 传入 Web SDK │
└────────┬───────────┘ └──────────┬─────────────┘
│ │
▼ ▼
┌────────────────────┐ ┌────────────────────────┐
│ Flutter SDK │ │ Web SDK │
│ │ │ │
│ 内部 AES-256-GCM │ │ 内部 AES-256-GCM │
│ 解密密文 │ │ 解密密文 │
│ 使用 domainList │ │ 使用 domainList │
│ 使用 eventList │ │ 使用 eventList │
│ 批量上报事件 │ │ 批量上报事件 │
└────────────────────┘ └────────────────────────┘关键设计原则
密文不解密原则
配置内容以 AES-256-GCM 加密后在网络传输。业务服务端和客户端始终持有密文,解密只发生在 SDK 内部。
- 业务服务端拿到密文 → 存储密文 → 透传密文
- 客户端拿到密文 → 原样传入 SDK
- SDK 拿到密文 → 内部解密 → 使用结果
最新优先,缓存兜底
服务端拉取策略:
| 情况 | 处理方式 |
|---|---|
| 本次拉取成功 | 更新缓存,返回最新密文 |
| 本次拉取失败,有历史缓存 | 返回上次成功缓存的密文 |
| 本次拉取失败,无历史缓存 | 按约定返回空值或错误状态,由客户端决策兜底方案 |
SDK 独立管理上报域名
SDK 解密配置后,内部维护可用域名列表(domainList)和事件白名单(eventList),并自行完成域名测速、上报调度等逻辑,业务方无需干预。
组件职责边界
业务服务端职责
✅ 定时调用 /sdk/getAvailableDomainList
✅ 缓存返回的密文 data
✅ 提供客户端接口,返回密文 data
✅ 失败时返回上次缓存
❌ 不解密 data
❌ 不修改 data
❌ 不解析 domainList / eventList
客户端职责
✅ App/页面启动时调用业务服务端接口
✅ 获取密文 data
✅ 将 data 原样传入 SDK
❌ 不解密 data
❌ 不修改 data
SDK 职责
✅ 接收密文 data
✅ 内部完成 AES-256-GCM 解密
✅ 使用 domainList 作为上报域名候选
✅ 使用 eventList 过滤事件上报
✅ 自动测速选最优域名
✅ 批量队列上报