这是 Beta 探索课程,内容结构、实验步骤和示例可能会继续调整。
关键决策回顾
那些让我纠结到凌晨三点的选择
回头看”光影”的 6 个月开发历程,技术方案的选型并不是一路顺风的。很多决策当时纠结了很久——甚至有几个选择,我后来发现并非最优解。
这一章,我想诚实地回顾每一个关键决策:当时考虑了什么、放弃了什么、结果如何。
决策 1:为什么先审后处理?
背景:用户上传一张图片后,是先审核内容再生成缩略图,还是先生成缩略图再审核?
方案 A:先审后处理(最终选择)
用户上传 → 审核 → 通过 → 生成缩略图 → 可见
方案 B:先处理后审核
用户上传 → 生成缩略图 → 审核 → 通过后可见
方案 C:边审边处理
用户上传 → 审核 + 处理并行 → 汇合 → 可见但这个决策有一个副作用:用户上传后需要等审核完成(200ms1s)再等处理完成(13s),总共 2~4 秒才能看到图片。我通过在审核通过后立即返回”上传成功”、后台异步处理缩略图来缓解这个问题。
决策 2:为什么客户端直传 OSS?
背景:图片上传可以走服务器中转,也可以让客户端直接传到 OSS。
方案 A:客户端直传 OSS(最终选择)
客户端 → OSS(通过 STS 临时凭证)
方案 B:服务器中转
客户端 → 应用服务器 → OSS
方案 C:服务器中转 + 流式转发
客户端 → 应用服务器(流式转发)→ OSS直传的风险:用户可能绕过审核,直接访问 OSS 上的原图。我通过以下措施防护:
决策 3:为什么选 WebP 作为主力格式?
背景:现代图片格式有 WebP 和 AVIF 两种选择。
方案 A:WebP 为主 + AVIF 辅助(最终选择)
方案 B:AVIF 为主 + WebP 兜底
方案 C:只用 WebP
方案 D:只用 JPEG(不转码)前端实现:
事后评估:这个决策基本正确,但有一个遗憾——AVIF 的编码速度确实太慢。如果当时选择”AVIF 异步生成 + WebP 同步返回”,用户体验会更好。
决策 4:为什么用消息队列而不是直接调用?
背景:审核和处理是异步流程,可以用消息队列解耦,也可以直接在代码里调用。
方案 A:消息队列(RabbitMQ)(最终选择)
上传服务 → RabbitMQ → 审核服务 → RabbitMQ → 处理服务
方案 B:直接 HTTP 调用
上传服务 → HTTP 调用审核服务 → HTTP 调用处理服务
方案 C:数据库轮询
上传服务写入数据库 → 审核服务轮询数据库 → 处理服务轮询数据库队列配置细节:
决策 5:为什么用 CDN 边缘裁剪而不是预生成所有尺寸?
背景:缩略图可以预先全部生成,也可以在 CDN 边缘实时裁剪。
方案 A:预生成固定尺寸 + CDN 边缘裁剪兜底(最终选择)
方案 B:完全预生成所有尺寸
方案 C:完全依赖 CDN 边缘裁剪决策 6:为什么文件命名用日期+哈希而不是自增 ID?
背景:图片存储路径可以有多种命名方式。
方案 A:日期 + 哈希(最终选择)
originals/2024/06/a3/d4e5f6...jpg
方案 B:自增 ID
originals/00001.jpg, originals/00002.jpg, ...
方案 C:用户 ID + 时间戳
originals/user_123/1717286400.jpg
方案 D:UUID
originals/550e8400-e29b-41d4-a716-446655440000.jpg所有决策一览
┌───────────────────┬──────────────────────┬────────────────────────────────┐
│ 决策问题 │ 最终选择 │ 核心理由 │
├───────────────────┼──────────────────────┼────────────────────────────────┤
│ 审核/处理顺序 │ 先审后处理 │ 省处理资源,防违规进 CDN │
│ 上传链路 │ 客户端直传 OSS │ 省带宽,快,支持分片 │
│ 图片格式 │ WebP 主力 + AVIF 辅助│ 97% 支持率 + 渐进增强 │
│ 异步通信 │ RabbitMQ 消息队列 │ 解耦,缓冲,可扩展 │
│ 缩略图策略 │ 预生成 + 边缘裁剪 │ 95% 场景预生成,5% 边缘兜底 │
│ 文件命名 │ 日期 + 内容哈希 │ 可管理 + 无热点 + 可去重 │
│ CDN 选型 │ 阿里云 CDN │ 国内节点多,与 OSS 同厂商 │
│ 存储方案 │ 阿里云 OSS │ 无需运维,按需付费 │
│ 监控方案 │ Prometheus+Grafana │ 开源免费,生态丰富 │
│ 数据库 │ PostgreSQL │ JSON 支持好,事务可靠 │
└───────────────────┴──────────────────────┴────────────────────────────────┘决策模式总结
回看这些决策,我发现了三个模式:
那些”如果重来”的决策
不是所有决策都是最优的。诚实地记录那些我后悔的选择: