秒杀系统架构设计03:动静分离与分层架构 秒杀的动静分离与分层架构本文是「10Wqps 秒杀架构」系列的第三篇聚焦系统分层设计和动静分离策略——这是控制流量水位、保护核心服务的第一道工程防线。一、开篇上一篇文章 我们分析了异步下单架构如何将同步耗时从 500ms 降至 30ms让单个 Tomcat 实例的吞吐从 400 qps 提升到 6000。但如果 100W qps 的用户请求全部直接打到 Tomcat 上即便每个请求只要 30ms仍然需要 5000 个以上的 Tomcat 实例——这在成本和运维上是不可接受的。真正高效的秒杀架构必须在请求到达业务服务之前就拦截掉绝大多数流量。这就是分层架构和动静分离要解决的问题。二、问题拆解2.1 各层组件的并发能力差异在电商架构中不同基础设施组件的并发能力存在数量级的差异单机/单集群 QPS 上限 Nginx ████████████████████ 10W Redis Cluster ████████████ 5W Tomcat █ 800~1000 MySQL (写) █ 1000~2000核心矛盾一目了然Nginx 能扛 10WTomcat 只能扛 800。如果把 Nginx 接收到的所有请求都透传给 TomcatTomcat 会成为整个链路的塌陷点。2.2 什么样的请求不需要打到服务端分析一个秒杀活动的页面流量结构静态资源HTML、CSS、JS、商品图片占总请求量的 90% 以上内容在秒杀期间不变动态请求exposed-key 获取、库存查询、下单仅占总请求量的不到 10%如果能将 90% 的静态请求拦截在服务端之前业务服务的压力就只剩下原来的 1/10。三、核心方案3.1 三层架构清晰的职责边界秒杀系统的物理部署分为三层每一层有明确的职责和并发能力要求┌─────────────────────────────────────────────────────┐ │ 客户端层 │ │ 职责内容提速 交互控制 │ │ 手段按钮置灰、60s 频率控制、URL 延迟暴露 │ ├─────────────────────────────────────────────────────┤ │ 接入层 │ │ 职责认证、负载均衡、限流 │ │ 组件Nginx CDN SpringCloud Gateway │ │ 策略动静分离、限流拦截、负载均衡 │ ├─────────────────────────────────────────────────────┤ │ 业务层 │ │ 职责保障秒杀数据一致性 │ │ 组件抢购服务、订单服务、库存服务 │ │ 手段分布式锁、MQ 异步、Lua 原子操作 │ └─────────────────────────────────────────────────────┘客户端层负责在用户设备上就拦截无效操作。秒杀按钮在活动开始前置灰 不可见 URL点击后 60 秒内禁止重复提交以及验证码人机校验。接入层作为服务端的第一道防线承担三个核心功能认证验证 Token 合法性拦截未登录或伪造请求负载均衡Nginx 采用权重 IP 哈希混合策略将请求分发到不同的 Gateway 节点限流按用户、商品、接口三个维度进行流量控制详见高可用篇业务层只处理经过前两层过滤后剩余的有效请求专注保障数据一致性——库存幂等扣减、订单不丢失、不重复。3.2 网关架构内部网关 vs 外部网关对于不同体量的系统网关的部署方式有所不同方案一内部网关承担全部职责适用于中小流量Nginx → SpringCloud Gateway认证 限流 路由→ 业务服务单个 Gateway 集群同时完成认证和限流。部署简单适合 QPS 在万级别的场景。方案二外部网关 内部网关分层适用于大流量Nginx → 外部网关限流如 OpenResty 自研插件 → SpringCloud Gateway认证 路由→ 业务服务限流职责前置到外部网关在请求进入内网之前就完成流量控制。内部网关专注于认证和路由压力更小。适合 QPS 在十万级别以上的场景。为什么大流量场景要将限流外置因为限流逻辑相对固定令牌桶、滑动窗口而认证逻辑涉及用户中心 RPC 调用、Token 解析等操作。将两者分离各自独立扩容避免限流模块被认证模块的慢调用拖垮。3.3 动静分离CDN 静态化的组合拳动静分离是整个架构中性价比最高的优化手段。静态资源处理路径用户 → CDN 边缘节点 → (缓存命中) 直接返回 → (缓存未命中) 回源 Nginx → 返回并缓存到 CDN秒杀活动页面的 HTML、CSS、JS、商品图片、详情描述全部静态化提前推送到 CDN。用户在活动开始前浏览商品信息时请求全部在 CDN 层面解决不经过服务端。动态内容处理路径用户 → Nginx → Gateway → 业务服务 → Redis只有两类动态请求需要穿透到服务端exposed-key 获取秒杀时间点到达后JS 发起异步请求获取 exposed-key用于点亮秒杀按钮和露出下单 URL。秒杀下单 订单轮询用户点击秒杀按钮后的下单请求以及三阶段异步架构中的轮询请求。exposed-key 的设计要点时效性key 有过期时间通常 5-10 分钟过期后自动失效一次性同一 key 只能被一个用户使用一次可选视业务需求而定签名校验key 包含服务端签名防止客户端伪造3.4 完整请求链路含 CDN静态资源缓存命中缓存未命中动态请求负载均衡限流是否否是用户请求请求类型CDN 边缘节点返回静态内容Nginx 源站Nginx 集群Gateway 集群是否被限流返回 429认证校验Token 有效返回 401路由到业务服务抢购/订单服务经过 CDN Nginx Gateway 三道过滤后真正到达业务服务的请求量约为原始请求量的5-10%。这正是漏斗模型在分层架构中的具体体现。3.5 除了分层和动静分离还有哪些配套手段秒杀架构不是一个单点方案而是一个组合策略。除了动静分离和分层架构还需要以下手段协同工作CDN 加速将静态资源分发到离用户最近的边缘节点降低网络延迟缓存体系构建 CDN → Nginx Cache → Caffeine → Redis 四级缓存体系MQ 异步将下单、通知等重操作异步化上篇文章已详述限流在接入层对用户、商品、接口三个维度限流分布式锁在业务层保障库存扣减的原子性弹性扩容基于 K8s HPA 在活动期间自动扩容业务服务实例四、边界与异常4.1 CDN 缓存刷新延迟CDN 节点的缓存刷新不是实时的。如果活动页面有紧急修改如价格错误CDN 缓存可能需要 5-15 分钟才能全部刷新。应对方案在 CDN 管理后台触发主动刷新同时设置合理的缓存 TTL秒杀场景下建议 30 分钟既利用缓存又能及时更新。4.2 Nginx 单点故障如果只有单台 Nginx一旦故障则全网不可访问。应对方案Nginx 集群部署 Keepalived 虚拟 IP主节点故障时自动切换到备节点切换时间 1 秒。4.3 Gateway 成为瓶颈如果 Gateway 实例不足限流和认证会成为链路瓶颈。应对方案Gateway 也是无状态的可以水平扩展。通过 K8s HPA 根据 CPU/内存/QPS 自动调整实例数。活动前 30 分钟预扩容到预估峰值所需的实例数。4.4 动静分离不彻底如果活动页面中嵌入了动态元素如实时库存数量这个动态请求会绕过 CDN 直接打到服务端。大量用户刷新页面时这个动态请求会成为新的瓶颈。应对方案将动态元素也缓存到 CDN更新频率设置为 5-10 秒通过 CDN 的定时回源或主动推送展示约剩余 XX 件而非精确数字。五、总结分层架构的本质是逐层过滤客户端拦截非法操作 → 接入层限流和认证 → 业务层专注数据一致性。每一层都有独立的扩容策略。动静分离是性价比最高的优化将 90% 的静态请求拦截在 CDN服务端只需应对 10% 的动态请求成本能力和效果立竿见影。网关职责应随体量调整中小流量场景 Gateway 承载全部职责大流量场景限流外置到独立网关各司其职。exposed-key 是动静分离的动态桥梁在保持页面静态化的前提下通过 key 机制精准控制秒杀暴露时机。分层架构解决的是请求如何到达正确的地方接下来的缓存篇将解决到达的请求如何被高效处理。