c26d6b9a73
Reviewer findings on p5-prep batch:
1. BLOCKING: prod-smoke.sh visibility grep used "id" but API items
serialize photoId (cn public.service / ov public-ov.service) — every
healthy deployment would false-FAIL release gate ④. 4 sites fixed.
2. web/web-ov healthchecks used curl on nginx:alpine (absent) → perpetual
false-unhealthy; switched to busybox wget.
3. RUNBOOK rollback rule cited nonexistent sync_outbox → outbox_events.
4. cdn-checklist invalidation sample key shape aligned to actual
variantsObjectKey layout (.../albums/{albumId}/variants/{photoId}/{version}/{variant}.jpg).
Co-Authored-By: Claude Code <noreply@anthropic.com>
146 lines
10 KiB
Markdown
146 lines
10 KiB
Markdown
# 阿里云全球 CDN 接入核对单(P5-prep Task 3)
|
||
|
||
> **全部步骤「待凭证执行」**:本清单只固化决策与命令样例,不预设任何已执行
|
||
> 状态。凭证/域名到位(G5)后按 T5 逐项勾选。关联:RUNBOOK.md §5.3(无 CDN
|
||
> 基线的缓存故障排查)、总纲 P5 行、`docs/plans/2026-09-21-P5-真实环境接入.md` T5。
|
||
|
||
## 0. 前置决策:图片加速三选一(重要架构核对,登记为 P5 决策项)
|
||
|
||
**现状(代码事实)**:图片一律走 **OSS presigned GET 直链**(S3 兼容 SigV4 签名,
|
||
`SIGNED_URL_TTL_SECONDS=900s`;variants 内容寻址键 `photoId+规格`,公开列表每次
|
||
现签 `thumb.url` / `browse.url`)。若 CDN 图片域名开启 **CDN 自己的 URL 鉴权**,
|
||
客户端 URL 将出现「CDN 签名参数 + OSS 签名参数」双层签名:CDN 校验自己的鉴权
|
||
参数后回源时带原 query 请求 OSS,OSS 再验自己的签名——两层参数互不冲突但
|
||
**缓存键含全部 query**,每个 900s 签名版本各成一册缓存,命中率崩塌;若为命中率
|
||
忽略 query,鉴权语义又互相残废。三个候选方案:
|
||
|
||
| 方案 | 内容 | 评估 |
|
||
| --- | --- | --- |
|
||
| a) 图片域名 CDN 仅缓存不鉴权 | 关 CDN 鉴权 + 忽略 query 参数缓存,依赖「OSS presign 过期」兜底 | **失效语义劣化**:presign 过期只约束回源,CDN 缓存内对象在 TTL 内仍可命中;忽略 query 后鉴权退化为「对象键不可猜」(cuid 随机,强度可接受但低于签名);隐藏照片失效窗口 = CDN 缓存 TTL,需配合主动失效。仅缓存静态 variants 可接受,收益有限 |
|
||
| b) CDN 鉴权 + 回源 OSS 私有桶 | 图片域名开 CDN URL 鉴权(B 型),回源用阿里云「CDN 授权访问 OSS 私有 Bucket」(§2),服务端 `presignGet` 改签 CDN 鉴权 URL | **正解但需改造**:签名安全模型从「OSS SigV4」迁到「CDN 鉴权」,`packages/storage` 的 presignGet 需按环境切换签名后端(或双签并存灰度);改造量集中在 storage 适配层 + 契约(URL 形态变化对前端透明,仍是无差别 URL 字符串)。**图片加速收益明确后采用** |
|
||
| **c) 【推荐起步】保持 presigned 直链 + CDN 仅加速 viewer 静态资源** | 只建 viewer 域名加速区(§1 Zone 1),图片域名 Zone(§1 Zone 2)暂不接入 | **最小改动、签名安全模型不变、零代码**;图片加速收益(900s 内重复读同图省回源带宽)先观察 OSS 流量账单再评估 b |
|
||
|
||
**推荐:c 起步**,图片流量账单 / 海外首屏时延数据到位后按 b 改造(a 不推荐,
|
||
失效语义与鉴权强度双损)。已登记为 P5 决策项(T5 内定案)。
|
||
|
||
## 1. 添加加速域名(待凭证执行;两 Zone)
|
||
|
||
| # | 加速域名 | 业务 | 源站 | 状态 |
|
||
| --- | --- | --- | --- | --- |
|
||
| Zone 1 | `<ov viewer 域名>`(如 photo.example.com) | viewer/admin SPA 静态 + `/v1/` API 透传 | ov 服务器 OpenResty 公网 IP(源站协议 https 回源 8089 需开白名单) | ☐ 待凭证执行 |
|
||
| Zone 2 | `<图片域名>`(如 img.example.com,CNAME 至同一 OSS 桶) | OSS 图片加速 | OSS Bucket(私有,需 §2 回源授权) | ☐ 待凭证执行(**方案 c 起步 = 本 Zone 暂缓创建**) |
|
||
|
||
每个 Zone 通用步骤(控制台:CDN → 域名管理 → 添加域名,业务类型「图片小
|
||
文件」/「小文件下载」;全球加速 = 不限区域或选「全球」):
|
||
|
||
- [ ] 添加域名 + 选择业务类型 + 源站信息(Zone 1 填 ov 服务器 IP;Zone 2 选
|
||
OSS 域名源站)
|
||
- [ ] CNAME 解析(DNS 服务商把域名 CNAME 到 CDN 分配的 `*.w.kunlun*.com`)
|
||
- [ ] HTTPS:申请/绑定证书 + 开启「强制 HTTPS」+(可选)HTTP/2
|
||
- [ ] 回源 Host 按默认(Zone 2 回源 Host = OSS 桶域名,控制台自动处理)
|
||
|
||
## 2. 源站 = OSS 私有 Bucket 回源授权(仅 Zone 2 / 方案 b 时需要;待凭证执行)
|
||
|
||
阿里云 CDN 回源私有 OSS 需授权二选一:
|
||
|
||
| 方式 | 操作 | 适用 |
|
||
| --- | --- | --- |
|
||
| 方式一:控制台一键 OSS 授权 | CDN 控制台源站配置时点「授权」,按提示同意创建 `AliyunCDNDefaultRole`(云账号级,授予 CDN 读 OSS 权限) | 最快,个人账号推荐 |
|
||
| 方式二:自定义 RAM 角色 | RAM 控制台创建角色(受信实体=CDN)+ 最小权限策略(仅目标桶 `oss:GetObject`)+ CDN 源站配置选该角色 | 多项目共用账号、需权限隔离时 |
|
||
|
||
- [ ] 按 §0 决策结果确定是否执行本节(方案 c 起步则整节跳过)
|
||
|
||
## 3. URL 鉴权选型(仅 Zone 2 / 方案 b;待凭证执行)
|
||
|
||
| 型式 | URL 形态 | 特点 |
|
||
| --- | --- | --- |
|
||
| A 型 | `md5(<uri>-<timestamp>-<rand>-<uid>-<key>)` 拼接,时间戳进 MD5 不可读 | 更防猜测,但排障时无法从 URL 直接看出过期时刻 |
|
||
| **B 型【推荐】** | `http://…/<uri>-<timestamp>-<md5hash>`,时间戳明文 | **时间戳在 URL 可读可调试**(一眼判过期);CDN 控制台配置简单(主备 key 各一个);鉴权粒度与 A 型同级 |
|
||
|
||
推荐 B 型理由:现场排障(观众报「图裂」)能直接从 URL 读出时间戳判断是否过期
|
||
窗口问题;主备 key 支持平滑轮换。**与现有 presigned GET 的关系**:方案 b 下
|
||
`presignGet` 输出从 OSS SigV4 URL 改为 CDN B 型鉴权 URL(§0 表格);方案 c 下
|
||
无任何 URL 鉴权变更(Zone 1 静态资源不鉴权,本来就公开)。
|
||
|
||
- [ ] 若定案方案 b:Zone 2 配置 B 型鉴权 + 主备 key(`openssl rand -hex 32`)
|
||
- [ ] 服务端 presignGet 签名后端改造排期(storage 适配层 + 测试)
|
||
|
||
## 4. 缓存规则表(Zone 1;待凭证执行)
|
||
|
||
原则:**源站 photo-live-web 已对内容寻址路径发 `Cache-Control: immutable`**
|
||
(`infra/deploy/nginx.conf.template`),CDN 遵循源站头即可,无需重配长 TTL。
|
||
计划占位稿中的「/assets/ 7d」按此修正为遵循源站 immutable(内容寻址键允许,
|
||
发新版 = 新 URL,无失效问题)。
|
||
|
||
| 路径 | CDN 缓存策略 | 依据 |
|
||
| --- | --- | --- |
|
||
| `/embed/v1/*` | 遵循源站:immutable 一年 | 版本目录即内容版本(nginx 同规则) |
|
||
| `/assets/*`、`/admin/assets/*` | 遵循源站:immutable 一年 | vite 内容寻址产物 |
|
||
| `/`、`/index.html`、`/admin/`、`/admin/index.html`、SPA 回退路径 | **不缓存**(no-cache,每次回源) | 发布新版必须立即生效,HTML 引用新 hash 的 assets |
|
||
| `/v1/*`(API/WS) | **不缓存** + 透传 `x-request-id` 头 | 动态 API;WS 经 CDN 需在 CDN 侧确认支持或对 `/v1/realtime` 单独跳过 CDN(建议 DNS 直连源站,见 §7 注意) |
|
||
|
||
- [ ] 按上表在 CDN 控制台配置缓存规则(HTML/回退路径显式 no-cache 兜底——
|
||
源站对 `index.html` 未显式发 no-cache 头,CDN 侧补齐这道保险)
|
||
- [ ] 验证:`curl -sI https://<域名>/ | grep -i cache` 确认未命中缓存
|
||
|
||
## 5. 失效 / 预热 API 样例(待凭证执行)
|
||
|
||
阿里云 CDN OpenAPI 需 AccessKey 签名(ACS3-HMAC-SHA256),raw curl 组签名繁琐,
|
||
**推荐 aliyun CLI 形态**(`aliyun` CLI 配置凭证后即用;curl 等价样例在凭证到位
|
||
后按官方签名文档补齐——本节全部待凭证执行):
|
||
|
||
```bash
|
||
# 隐藏照片 → 失效该照片全部 variants 路径(对象键含 photoId 与内容版本;
|
||
# 方案 b 下才需要——variants 是 immutable 缓存,隐藏 = 主动失效 + 公开 API 404 双保险)
|
||
# 多 URL 用换行分隔(RefreshObjectCatches/PreloadObjectCaches 的 ObjectPath 约定)
|
||
aliyun cdn RefreshObjectCaches \
|
||
--ObjectPath "$(printf '%s\n%s' \
|
||
'https://<图片域名>/photo-live/prod/albums/<albumId>/variants/<photoId>/<version>/thumb.jpg' \
|
||
'https://<图片域名>/photo-live/prod/albums/<albumId>/variants/<photoId>/<version>/browse.jpg')" \
|
||
--ObjectType File
|
||
|
||
# 新活动发布 → 预热首页与首屏静态资源(viewer 域名,降低冷缓存首访时延)
|
||
aliyun cdn PreloadObjectCaches \
|
||
--ObjectPath "$(printf '%s\n%s' \
|
||
'https://<viewer域名>/assets/<新版本hash>.js' \
|
||
'https://<viewer域名>/assets/<新版本hash>.css')"
|
||
|
||
# 目录级失效(发版后 SPA HTML 变更;范围大时用,注意每日失效配额)
|
||
aliyun cdn RefreshObjectCaches --ObjectPath "https://<viewer域名>/" --ObjectType Directory
|
||
```
|
||
|
||
- [ ] 隐藏照片失效窗口验证(方案 b 时):上传 → 公开可读 → 隐藏 → 立即请求
|
||
variants URL:公开 API 应 404(PHOTO_NOT_PUBLIC),CDN 失效执行完成后
|
||
图片 URL 应 403/404;**失效前的窗口 = 设计允许的失效窗口**(对齐 P4a
|
||
契约决策与 RUNBOOK §5.3,CDN 侧窗口上限 = 失效 API 生效延迟,需实测
|
||
登记进 RUNBOOK)
|
||
- [ ] 发版后预热纳入发布检查单(RUNBOOK §1 增补一行,待 CDN 实际接入后回填)
|
||
|
||
## 6. 冷缓存测试点(海外多地域时延记录表模板)
|
||
|
||
各地域单点拨测(冷缓存 = 首次请求回源;建议每地域 `curl` 3 次取中位),模板:
|
||
|
||
| 地域(测试点) | 测试方式 | 冷缓存 TTFB/总时延 | 热缓存复测 | 时间 | 备注 |
|
||
| --- | --- | --- | --- | --- | --- |
|
||
| 新加坡 | `curl -s -o /dev/null -w '%{time_starttransfer} %{time_total}\n' https://<viewer域名>/` | ___ / ___ | ___ | ___ | |
|
||
| 东京 | 同上 | ___ / ___ | ___ | ___ | |
|
||
| 法兰克福 | 同上 | ___ / ___ | ___ | ___ | |
|
||
| 美西(硅谷) | 同上 | ___ / ___ | ___ | ___ | |
|
||
| 美东(弗吉尼亚) | 同上 | ___ / ___ | ___ | ___ | |
|
||
| 国内对照(杭州) | 同上 | ___ / ___ | ___ | ___ | 不走全球 CDN 国内段时的对照基线 |
|
||
|
||
可选公共拨测源:阿里云云监控站点监控(多地域)、第三方(如 GTmetrix / WebPageTest)
|
||
留档截图。记录表随 T5 产出归档进 P5 验收记录。
|
||
|
||
## 7. 注意事项与边界
|
||
|
||
- **WS(`/v1/realtime`)不适合过 CDN**:长连接透传稳定性依赖 CDN 支持;建议
|
||
viewer 前端 WS 地址直连源站域名(或单独一个不接 CDN 的子域),CDN 只加速
|
||
静态与普通 API。核对前端 realtime 连接 URL 的构造(P5 T4/T5 联合验证项)。
|
||
- Zone 1 源站是 ov 服务器 OpenResty:CDN 回源 IP 段需加入 OpenResty 白名单
|
||
(1Panel 防火墙),并确认回源走 https(证书已就绪)。
|
||
- 速率/配额:CDN 每日失效/预热有配额(控制台可见),发版高频期优先用文件级
|
||
精确失效;目录级失效作为兜底。
|
||
- 全部步骤执行前保持「无 CDN」基线可用(RUNBOOK §5.3),CDN 故障时 DNS 切回
|
||
直连即回滚(T8 演练项之一)。
|