这是 Beta 探索课程,内容结构、实验步骤和示例可能会继续调整。
完整系统
回顾这段旅程
到这一章,图片 CDN 系统已经不再是”上传一张图并返回一个 URL”的简单功能,而是一套覆盖上传、存储、处理、审核、分发、观测和成本治理的内容基础设施。
回头看这段旅程,我们从最简单的本地存储开始,经历了对象存储、异步处理、内容审核、CDN 加速、成本优化,每一步都是被真实的业务问题推着往前走的。
完整架构的重点,是让每个模块各司其职,同时通过清晰状态和事件流串成一个可靠闭环。
最终架构
最简实现:Flask + 本地磁盘,无 CDN,无压缩
用户层
用户浏览器直接访问服务器
应用层
Flask 服务器1 核 2G,5Mbps 带宽
存储层
本地磁盘100GB,无冗余
客户端直传 OSS + 缩略图生成 + WebP 转换
用户层
用户浏览器直传 OSS
应用层
上传服务签发 STS 凭证
处理服务缩略图 + WebP
存储层
阿里云 OSS原图 + 缩略图
PostgreSQL元数据
CDN 全球加速 + 内容审核 + 异步处理队列
用户层
用户浏览器就近访问 CDN
CDN 层
阿里云 CDN2800+ 节点,边缘裁剪
应用层
上传服务×3签发凭证 + 回调
审核服务×2鉴黄 + OCR
处理服务×4多尺寸 + WebP/AVIF
数据层
阿里云 OSS标准 + 低频 + 归档
RabbitMQ异步处理队列
PostgreSQL元数据 + 用户
生产级图片系统:12,000 用户,85,000 张图片,月成本 ¥1,720
用户层
用户浏览器<picture> + 懒加载
CDN 层
阿里云 CDN缓存命中率 96%,边缘裁剪
服务层
上传服务×3STS 凭证 + 频率限制
审核服务×2鉴黄 + OCR + 人审
处理服务×4多尺寸 + EXIF
数据层
阿里云 OSS标准 + 低频 + 归档
RabbitMQupload→audit→process
辅助系统
PrometheusCDN 命中率 / 延迟
Grafana监控面板 + 告警
最终链路可以这样理解:
- 客户端申请上传凭证 → 向业务服务请求签名 URL
- 直传对象存储 → 客户端直传,不经过业务服务器,节省带宽
- 写入元数据 + 发布事件 → 上传完成后写入图片元数据表,发布处理事件
- 压缩服务消费事件 → 生成多格式、多尺寸派生图,写回元数据
- 审核服务消费事件 → 机审+人审,决定图片是否允许展示
- CDN 分发 → 根据稳定缓存键分发已通过审核的版本
- 生命周期任务 → 根据访问热度和业务状态迁移或清理对象
每一步都要能重试、追踪和降级。
核心模块职责
| 模块 | 职责 | 关键设计 |
|---|---|---|
| 上传服务 | 签发凭证、接收上传回调、写入元数据 | 客户端直传、幂等回调、元数据先写 |
| 对象存储 | 原图和派生图的持久化 | 多副本、跨可用区、生命周期管理 |
| 压缩服务 | 生成多格式多尺寸派生图 | 异步消费、可重试、场景化策略 |
| 审核服务 | 机审+人审,决定可见性 | 状态机、低置信度转人审、已发布召回 |
| CDN | 边缘加速、缓存、安全防护 | 稳定缓存键、签名 URL、防盗链 |
| 元数据服务 | 图片信息、状态、成本数据 | 强一致、可查询、驱动生命周期 |
| 观测系统 | 监控、告警、链路追踪 | 全链路追踪、SLO 告警、成本报表 |
关键取舍
系统设计没有银弹,每个决策都是权衡:
原图是否永久保留?
- 保留:可以随时重新生成派生图,支持格式升级(比如未来出现更好的格式)
- 不保留:节省存储成本,但无法回溯
- 我们的选择:原图永久保留(存储成本远低于重新获取的成本),派生图可删除
派生图预生成还是按需生成?
- 预生成:访问速度快,但存储成本高,很多派生图从未被访问
- 按需生成:节省存储,但首次访问延迟高
- 我们的选择:热门尺寸预生成+预热,长尾尺寸按需生成+缓存
审核前是否允许预览?
- 允许:用户体验好,但有违规内容短暂可见的风险
- 不允许:安全,但用户上传后要等审核完成才能看到
- 我们的选择:上传后立即生成低分辨率预览图(仅上传者可见),对外展示必须等审核通过
CDN 缓存如何与权限控制共存?
- 公开缓存:命中率高,但无法控制访问权限
- 签名 URL:安全,但缓存命中率低
- 我们的选择:公开图片用公开缓存,敏感图片用签名 URL+短缓存,通过业务层区分
故障恢复设计
每个模块都可能失败,系统要能优雅降级:
| 故障场景 | 降级策略 |
|---|---|
| 压缩服务宕机 | 原图直接对外展示,标记派生图待生成,恢复后异步补处理 |
| 审核服务宕机 | 新上传图片标记为”待审核”,暂不对外展示,不阻塞上传 |
| CDN 大面积故障 | 切换到备用 CDN 厂商,或直接回源(降级体验但保证可用) |
| 对象存储故障 | 切换到跨区域备份,RPO < 15 分钟 |
| 元数据服务故障 | 缓存层兜底,允许只读访问,写入排队等待恢复 |
扩展能力
当业务从头像扩展到商品图、社区图片、营销素材或多地区分发时:
- 哪些设计可以复用? —— 上传链路、压缩框架、审核状态机、CDN 缓存策略、成本模型
- 哪些地方必须重新评估? —— 图片尺寸范围(营销素材可能是 4K)、审核标准(商品图和社区图不同)、合规要求(不同地区数据驻留)、版权保护(原创图片需要水印和溯源)
验收标准
完成本章后,你应当能:
- 画出生产级图片平台的核心架构,标注每个组件的职责和依赖
- 说明每个组件解决什么问题,以及为什么需要这个组件而不是更简单的方案
- 解释关键取舍的理由,在什么业务约束下做了什么选择
- 设计故障恢复策略,每个模块失败时系统如何降级
- 判断扩展时的复用边界,哪些可以直接复用,哪些需要重新设计
更重要的是,你会具备判断能力:当面对一个新的图片业务场景时,能快速识别哪些设计可以直接套用,哪些地方需要根据业务约束重新评估。
这就是系统设计的核心——不是记住某个架构图,而是理解每个决策背后的权衡逻辑,能在不同的业务约束下做出合理的选择。
