一、通用秒杀架构概述
系统设计是一个由宏观到微观的过程。要设计好秒杀系统,首先需要深入理解其架构特点。本文将重点分析传统架构设计的特性,介绍最新的秒杀系统架构,并探讨技术选型和环境准备策略。
二、一般性系统架构分析
2.1 传统系统架构模式
常见的系统功能架构图展示了我们熟悉的模式:
在这种架构中,Nginx通常仅作为反向代理和负载均衡器,许多业务开发人员对此层无感知,通常由运维部门在生产环境搭建时配置。研发人员主要专注于Web服务和其他RPC服务/微服务的开发。我们将页面及其依赖的静态资源都放在Web服务中,同时Web服务提供业务接口,RPC服务提供支撑服务。
2.2 动静分离架构改进
经过动静分离优化后,VUE前端部分会部署在Nginx上,形成以下结构:
Nginx层:承载页面及静态资源
Web服务层:提供业务接口
RPC服务层:提供支撑服务
这种模式相比传统架构有所改进,但在秒杀场景下仍面临挑战。
三、页面访问问题分析
3.1 商详页访问压力
以商品详情页为例,商城进行动静分离后,商详页实现在product.vue中。每个商品都需要从后端获取详细信息进行展示:
javascript
mounted() { window.scroll(x:0, y:0); this.getProductInfo(); }, methods: { getProductInfo() { let id = this.$route.params.id; this.axios.get(`/pms/productInfo/${id}`).then((res) => { this.product = res; }); } }在高并发秒杀场景下,这种实现方式会对后端服务造成巨大压力,即使产品信息全部缓存,仍会消耗大量后端资源和带宽。
四、Web服务器性能瓶颈
4.1 Tomcat线程模型问题
通常我们使用Tomcat部署Web服务。Tomcat通过线程处理请求,这在秒杀场景下会带来问题:
线程激增:瞬时大量请求导致线程池不足,Tomcat会快速创建新线程,直至达到最大线程数
CPU过载:线程数设置过大可能导致CPU打满,机器宕机
请求拒绝:高负载下等待队列满后,后续请求被拒绝连接
4.2 扩展性限制
虽然可以通过增加机器分摊流量,但:
成本可能超出预算
还会面临读写热点、库存超卖等问题
五、常见的秒杀系统架构
5.1 大厂秒杀架构设计
结合秒杀各链路层级,大厂的秒杀功能结构与系统架构如下图所示:
该架构与一般系统架构的主要区别包括:
5.2 CDN静态资源加速
将原先由Web服务或Nginx提供的静态资源部署到CDN:
CDN遍布全国,客户端就近拉取静态资源
大大减轻秒杀域名的瞬时负担
显著提升页面加载速度
5.3 Nginx网关升级
最大的改变是将Nginx职责扩展为Web网关,承担部分业务逻辑校验:
黑白名单过滤
限流和流控功能
业务网关角色
这种模式在大公司中很常见:
京东:商详、秒杀业务网关
美团:负载均衡接入层
12306:车票查询网关
5.4 流量筛选策略
秒杀入口流量巨大但组成混杂:
刷子请求:约60%
无效请求:约10%
正常请求:约30%
网关层的核心任务是:
尽可能多地接收流量
精确筛选有效请求
将30%的正常请求分发到下游
拦截70%的无效和刷子请求
这样可以避免Web服务层浪费资源处理无效请求。
六、电商项目技术选型
电商项目秒杀系统技术选型的核心设计思路是对巨大的瞬时流量进行层层错峰:
6.1 错峰策略一:页面静态化
本质:将动态数据和静态资源分离
实现:商品信息等静态内容使用Freemarker模板引擎实现
优势:减少动态数据请求,提升页面加载速度
6.2 错峰策略二:秒杀前答题
目的:防止机器刷单,错开用户下单时长
实现:通过HappyCaptcha添加动态验证码
效果:答题速度靠后的请求自然减少,降低系统请求量
6.3 错峰策略三:Redis扣减库存
作用一:快速扣减库存,保护数据库
作用二:提前识别热点数据
优化方案:
优化:提升处理效率
限制:控制请求频率
隔离:业务、系统、数据隔离
6.4 错峰策略四:Nginx快速通知秒杀结束
实现:引入OpenResty增强Nginx功能
效果:秒杀结束后在网关层直接拒绝后续请求,保护后端服务
6.5 错峰策略五:MQ流量削峰
方式:通过MQ对前端并发请求进行削峰
效果:减少瞬间流量对后端服务器的压力
6.6 错峰策略六:下单服务异步化
实现:后端服务将下单消息发到MQ
优势:无需关心下游业务,减轻下单服务压力
七、OpenResty详解
7.1 简介
Nginx是为应对高并发网络请求场景而设计的,具有并发能力强、资源消耗低的特性。其五大优点包括:
模块化
事件驱动
异步
非阻塞
多进程单线程
OpenResty是Nginx的一个社区分支,由中国人章亦春发起。它是一个基于Nginx与Lua的高性能Web平台,集成了大量Lua库和第三方模块。
7.2 为什么选择Lua?
线程模型匹配:Lua采用单线程多协程模式,与Nginx的单进程单线程完美匹配
语法简洁:Lua是一种小巧的脚本语言,学习成本低
广泛应用:Redis也使用Lua作为脚本语言
推荐学习资料:豆瓣评分8分以上的Lua编程书籍。
八、OpenResty原理深入
8.1 Nginx进程模型
Nginx服务器启动后产生:
Master进程:接收外界信号,监控Worker进程
Worker进程:实际处理外部请求,数量通常与CPU核数一致
8.2 Nginx请求处理阶段
Nginx将HTTP请求处理划分为11个阶段:
| 阶段 | 名称 | 说明 |
|---|---|---|
| 1 | ngx_http_post_read_phase | 接收完整HTTP头部后处理 |
| 2 | ngx_http_server_rewrite_phase | URI重写(location匹配前) |
| 3 | ngx_http_find_config_phase | 寻找匹配的location配置 |
| 4 | ngx_http_rewrite_phase | location级别的URI重写 |
| 5 | ngx_http_post_rewrite_phase | 防止重写死循环 |
| 6 | ngx_http_preaccess_phase | 访问控制准备阶段 |
| 7 | ngx_http_access_phase | 访问权限控制 |
| 8 | ngx_http_post_access_phase | 访问控制后处理 |
| 9 | ngx_http_try_files_phase | try_files指令处理 |
| 10 | ngx_http_content_phase | 生成响应内容(最重要阶段) |
| 11 | ngx_http_log_phase | 日志记录 |
其中,HTTP无法介入的阶段有4个:3、5、8、9。
8.3 OpenResty的Lua插载点
OpenResty在HTTP处理阶段基础上为Lua脚本提供处理能力:
主要插载点包括:
init_by_lua:Master进程加载配置时运行
init_worker_by_lua:Worker进程启动时执行
set_by_lua:变量初始化
rewrite_by_lua:复杂转发、重定向逻辑
access_by_lua:IP准入、接口权限处理
content_by_lua:内容处理器,接收请求并输出响应
header_filter_by_lua:响应头部或cookie处理
body_filter_by_lua:响应数据过滤
九、总结
通用秒杀架构的设计核心在于:
层层错峰:通过多种策略分散瞬时流量压力
网关升级:将Nginx扩展为业务网关,承担更多逻辑处理
静态分离:充分利用CDN加速静态资源
异步处理:通过MQ实现流量削峰和业务异步化
技术选型:结合业务特点选择合适的技术栈,如OpenResty
这些设计原则不仅适用于秒杀系统,对于其他高并发场景也有重要参考价值。通过合理的架构设计,可以在有限的资源下支撑高并发业务,实现系统的高可用和高性能。