业务分析 系统挑战
- 瞬时流量
- 库存有限
- 持续时间短
- 预约,限购
- 涉及 商品详情页,订单结算,支付
要解决的问题
- 瞬时流量带来的服务端压力,造成单个请求增加。打挂服务器,用户体验不佳。
- 库存有限。造成多卖,超卖。
- 刷子流量,黄牛抢单,刷订单。黑产!道高一尺魔高一丈。
通用秒杀架构
问题分析
解决大流量问题
- Http请求路径
用户 -> DNS -> NGINX -> Web服务 -> RPC调用
解决流量问题,就是在链路上的个个节点进行优化。
NGINX:负载均衡,反向代理,静态资源服务器。流量过滤,限流。
Web服务:集群,业务聚合。
RPC调用:数据库,缓存等基础服务。
NGINX
流量筛选,缓存接口(openretry)
引入Openrestry 处理商品展示页面相关接口。
Nginx启动后,产生Master进程。Master生成多个Worker进程,处理相关请求。
Worker进程数可以配置。一般跟CPU数量保持一致。或者CPU跟Worker进行绑定,减少上下文切换,提升性能。
OpenRestry将LuaJIT的虚拟机嵌入到Nginx的管理进程和Worker进程。性能上OpenRestry接近或者超过C的模块,开发效率高。
Nginx将Http请求分成多个阶段,一个Http请求分给多个模块进行处理。每个模块专注一个独立简单的功能处理。
9个模块:
OpenRestry在Http处理阶段基础上分别在Rewrite/Access阶段、Content阶段、Log阶段注册了自己的Handler,加上系统初始阶段
Master的两个阶段,共11 个阶段为Lua脚本提供了介入的能力。
init_by_lua:进程加载Nginx配置文件时运行,一般用于注册全局变量,或者预加载Lua模块。
init_worker_by_lua:每个worker进程启动时执行,通常用于定时拉取配置数据或则进行后端服务的健康检查。
set_by_lua:变量初始化。
rewrite_by_lua:可以实现复杂的转发,重定向逻辑。
access_by_lua:准入,接口权限等情况集中处理。
content_by_lua:内容处理器,接收请求处理并输出响应。
header_filter_by_lua:响应头部或者Cookie处理。
body_filter_by_lua: 对响应数据进行过滤,如截断或者替换。
log_by_lua:会话完成后,本地异步完成日志记录。
商城中的OpenRestry
- 负载均衡
- 网关
- 反向代理
详情页静态化
页面:商品详情页静态化。比商城页面静态化更彻底的静态化。
秒杀的商品是独立提报的。秒杀商品详情页的模板是类似的。抽出相同部分,通过freemark生成静态页面,缓存到ftp服务器。通过nginx直接访问。
具体做法:
- 准备提报脚本,自动化处理 生成html静态文件。推送到nginx服务端。
- 秒杀管理后台,开启秒杀开关,选取商品进行商详面静态化。
- sftp 上传到nginx服务器。
- 访问链接和具体页面进行映射。通过RestyTemplate
- OpenRestry二次模板化。活动详情的渲染等。通过RestyTemplate
库存获取
库存:库存直接从redis进行获取。不用通过后端服务。
- OpenResty直接访问Redis获取库存。resty.redis开源模块。
- Nginx 和 Redis从服务器放在一起,避免链路层和传输层的开销。完全避免网络开销需要用到Unix Domain Socket变成进程间通信 IPC!
Unix Domain Socket: 进程间通讯。
秒杀隔离设计
隔离策略,秒杀商品和普通商品隔离。
如何隔离
- 业务上的隔离
- 系统隔离。流量大的系统进行隔离(订单,支付,库存)
- 数据的隔离