“秒杀”活动对于系统的挑战是高并发,高流量,持续时间集中,短时间内流量陡增数倍,甚至数十倍。今天,我们在京东618指挥中心,看看如何设计一个牛X的秒杀系统。
利用nginx作为代理服务器,解决系统高并发问题
1、nignx的稳定性
nginx采用master加多个worker进程,master只负责接收外界信号和监控work进程运行状况,当发现某个work进程出现异常,master进程会启动新的worker进程来,这样保证web服务的稳定性。
2、高并发的处理机制
nginx在启动的时候,每个work进程都会事先分配好自己的连接池,连接池的大小是配置文件中worker_connections参数配置。这里的连接池里保存的不是真实的连接,它只是一个worker_connections大小的一个ngx_connection_t结构的数组。
并且,nginx会通过一个链表f r e e _ c o n n e c t i o n s来保存所有的空闲ngx_connection_t,每次获取一个连接时,就从空闲连接链表中获取一个,用完后,再放回空闲连接链表里面。
当大量请求进来时,nginx首先会把它们放入work进程的连接池内,此时并没有真正打开文件描述符,因此可以尽可能多的接受连接请求,真正处理的时候nginx采用异步非阻塞的事件机制,通过单进程循环处理准备好的事件,最终利用有限的系统能打开的最大文件描述来承担大量的连接请求。
3、高并发下高性能
nginx中每个worker进程独立处理自己的连接请求,不会有进程来回切换带来的性能损失;单个worker进程与cpu的亲缘绑定,减少了因cpu抢占带来的性能损失;在linux系统中,nginx采用IO多路复用技术(epoll),同时打开大量文件描述符时worker进程只需要循环处理已经准备好数据的文件描述符,因此worker进程不会因为某个请求IO阻塞而影响其他请求的处理。
4、高并发下简单业务处理
因为nginx源生命令提供的功能单一,复杂的业务逻辑需要开发c模块,开发周期相对来说较长,且维护和升级复杂度较大。ngx_lua模块通过将lua解释器集成进Nginx,因此可以采用lua脚本实现业务逻辑,由于lua的紧凑、快速以及内建协程,所以在保证高并发服务能力的同时极大地降低了业务逻辑实现成本。
5、结算页的所有操作设置轻量级
主流程的任何操作都会将数据保存的缓存中,秒杀系统的结算页所有操作都尽可能的轻量级,将数据保存到隐藏域,提交是通过post请求调提交服务。
6、非关键性业务异步化
非关键性业务是指即使异步调用失败,也不会影响用户正常下单的系统,对于非关键性业务考虑异步化。
7、Java服务端的并发保护
为了保护秒杀系统后端的关键服务,需要进行并发限制的处理。比如调风控的服务,当每个tomcat实例并发连接数超过10个就放弃请求风控服务等类似的并发保护措施。
限制机器人刷单
秒杀系统为了便于用户下单,流程设计会尽量精简,因此不利于阻挡利用软件参与抢购的机器人,下面的几种实践方法,可以有效限制机器人刷单:
8. nginx层针对机器人做规则限制
在正常的下单流程中,用户通过单品页加入购物车,最后提交订单。这种简单的流程,通过数据分析,机器人很容易用软件构造数据,直接提交订单,因此在抢购过程中,会比普通用户快很多。
为了防止这种构造数据避过流程的软件,把秒杀活动分为几个环节:活动入口,验证码页,验证码交互,订单详情页,提交订单。几个环节环环相扣,以保障任何人都必须从入口一步步完成抢购活动,这种限定软件的行为轨迹,基本拉到和普通用户同样的水平,以增加普通用户成功抢购的几率。
技术实现:为了保证所有用户必须一步步访问,利用一个nginx的模块,来校验用户当前访问的步骤是否合法,并且把当前用户相关状态以加密串的形式种植在cookie中。Lua配合nginx模块的时候,可以进行复杂一些的业务逻辑方面的校验工作。
9. Java服务端做严格规则过滤
可以想像一个比较简单,快速的通道,即在本地进行一些数据的分析,比如当一个手机号1分钟内下单超过5次就认为这个下单行为是异常的,这条途径是比较快速,但是精准度稍有欠佳。可以配合使用调用远程风控服务的方式,提高精准度。风控服务可以通过大量的数据判断,这个用户是否是恶意订单。
秒杀系统的持续优化
10. nginx监控
目前现有的nginx监控,主要是根据nginx本身提供的status各个数据,这样只能监控到nginx本身的运行情况。但是nginx代理的后端,或者子请求的状况以及其他业务相关的信息无法获取。因此需要完善nignx生态的监控。
11. Web服务器端实时存储和校验用户访问行为
目前多数以加密cookie的形式记录用户的访问行为,当用户删除cookie并从入口页重新进入后,将无法获取用户以前的行为,只能当做新用户处理。
因此建议在服务器端实时存储用户的行为,这样不依赖cookie的校验,用户避开规则可能性就更小。并且减少加密cookie,每个请求都会减少一百多字节的数据,在高峰期减少cookie也可以起到节省带宽的作用。
本文作者:京东商城研发部 高建峰
全文刊登在《京东架构师》第五期
本文为原创作品,为尊重作者的劳动成果,请转发务必注明出处及作者。