动静分离+CDN 技术
动静分离分析
-
场景分析:在秒杀活动开启之前,用户一般都会尝试不断的刷新浏览器页面(俗称 F5)以保证不会错过秒杀活动的商品。
-
按照常用的网站应用架构:
-
我们假设,如果这些无用的请求,频繁的冲击我们的后台服务器,比如说经过:Web 服务器(LVS、Nginx 等)->应用服务器(tomcat 或者 Jetty 等)、连接数据库(MySQL),者无疑会对后端服务以及服务器造成非常大的压力。
-
解决方案:重新设计秒杀商品页面,不使用网站原来的商品详细页面,页面内容静态化,减少/隔绝无用的请求经过后端服务。
CDN 技术分析
增加网络带宽
网站的静态页面数据大小 100K,那么需要的网络和服务器带宽是 2G(100K×10000),这些网络带宽是因为秒杀活动新增的,超过网站平时使用的带宽。
即使将动态业务转换为静态化页面,但是秒杀活动会非常剧烈的增加的网络带宽的消耗,同时并不会减轻前端网站服务器的压力,所以如果可以的话,需要再进一步将秒杀商品页面缓存在 CDN,而不在是单纯的我们的前端 Nginx 服务器层面,所以需要和 CDN 服务商临时租借新增的出口带宽。
阻断缓存页面
在页面中加入一个 JavaScript 文件引用(进行传递随机号+状态位),该 JavaScript 文件
中包含秒杀开始标志为否;
-
当秒杀开始的时候生成一个新的 JavaScript 文件(文件名保持不变,只是内容不一样),更新秒杀开始标志为是,加入下单页面的 URL 及随机数参数(这个随机数只会产生一个,即所有人看到的 URL 都是同一个,服务器端可以用 redis 这种分布式缓存服务器来保存随机数),并被用户浏览器加载,控制秒杀商品页面的展示。
-
这个 JavaScript 文件的加载可以加上随机版本号(例如 xx.js?v=32353823),这样就不会被浏览器、CDN 和反向代理服务器缓存。
-
这个 JavaScript 文件非常小,即使每次浏览器刷新都访问 JavaScript 文件服务器也不会对服务器集群和网络带宽造成太大压力。
根据 ID 限制频率
为了控制公平性原则,由于黄牛或者一些黑客达人,会采用”高科技“,比如说,采用爬虫脚本操作,疯狂的去刷新页面。为了防止一些人的破坏以及公平分散,所以采用同一个标准去控制 UID(用户 ID)去访问频率信息,当超过每个人所需要达到的频率阈值,就要进行限制互动窗口内能够访问刷新的数据量!
例如:可以用 Redis 给每个用户做访问统计,根据用户的 ID 和商品的标识双方面进行对用户对某一个商品的访问频率控制,超过访问频率后,就会将他的请求暂时性熔断。
负载均衡
秒杀系统必然是一个集群系统,在硬件不提升的情况下利用 nginx 做负载均衡也是不错的选择。
负载均衡(Load Balance)是集群技术(Cluster)的一种应用,可以将工作任务分摊到多个处理单元,从而提高并发处理能力,有利于提升中大型网站的性能。需要使用服务集群和水平扩展,让“高峰”请求分流到不同的服务器进行处理。
http 协议负载均衡
根据用户的 http 请求的 DNAT 计算出一个真实的 web 服务器地址,并将该 web 服务器地址写入 http 重定向响应中返回给浏览器,由浏览器重新进行访问。该方式比较简单,但性能较差。
DNS 解析负载均衡
DNS 服务器上配置多个域名对应 IP 的记录。该方式直接将负载均衡的工作交给了 DNS,为网站管理维护省掉了很多麻烦,访问速度快,有效改善性能。
反向代理负载均衡
反向代理服务器在提供负载均衡功能的同时,管理着一组 web 服务器,根据负载均衡算法将请求的浏览器访问转发到不同的 web 服务器处理,处理结果经过反向服务器返回给浏览器。
网络层 IP 负载均衡
网络层通过修改目标地址进行负载均衡,该方式在响应请求时速度较反向服务器负载均衡要快,但是,当请求数据较大(大型视频或文件)时,速度反应就会变慢。
MAC 层负载均衡
数据链路层修改 Mac 地址进行负载均衡,负载均衡服务器的 IP 和它所管理的 web 服务群的虚拟 IP 一致。它不需要负载均衡服务器进行地址的转换,但是对负载均衡服务器的网卡带宽要求较高。
硬件负载均衡
F5 的全称是 F5-BIG-IP-GTM,硬件负载均衡设备,其并发能力达到。该方式能够实现多链路的负载均衡和冗余,可以接入多条 ISP 链路,在链路之间实现负载均衡和高可用。
服务层架构设计
降速机制
即使我们扩展再多的应用服务,使用再多应用服务器,部署再多的负载均衡器,都会遇到支撑不住海量请求的时候。
排队处理
排队处理就像我们日常买东西排队一样,将请求放入队列中的,采用 FIFO(First Input First Output,先进先出),这样的话,我们就不会导致某些请求永远获取不到锁。看到这里,有一些将多线程处理方式变成单线程处理机制,会大大影响数据的效率和性能!
阻塞队列
-
ArrayBlockingQueue 是初始容量固定的阻塞队列。
-
ConcurrentLinkedQueue 使用的是 CAS 原语无锁队列实现,是一个异步队列,入队的速度很快,出队进行了加锁,性能稍慢。
-
LinkedBlockingQueue 也是阻塞的队列,入队和出队都用了加锁,当队空的时候线程会暂时阻塞。
分批放行
在同步排队的基础上,可以再加入一个分批放行执行机制,我们可以考虑达到预定阈值以后,在进行相关的执行后端服务,这样子可以提高一定的性能以及减少后端请求的次数和压力,如下图所示:
利用缓存和队列技术减轻应用处理的压力,通过异步请求的方式做到最终一致性。
限流机制
漏桶算法
漏桶算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水,当水流入速度过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。
-
设定漏桶流出速度及漏桶的总容量,在请求到达时判断当前漏桶容量是否已满,不满则可将请求存入桶中,否则抛弃请求。
-
采用一个线程以设定的速率取出请求进行处理。
算法弊端
-
只能以特定速率处理请求,如果速率设置太小则会浪费性能资源,设置太大则会造成资源不足。
-
无论输入速率如何波动,均不会体现在服务端,即使资源有空余,对于突发请求也无法及时处理,故对有突发请求处理需求时,不宜选择该方法。
令牌桶算法
令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。
实现原理
设定令牌桶中添加令牌的速率,并且设置桶中最大可存储的令牌,当请求到达时,向桶中请求令牌(根据应用需求,可能为 1 个或多个),若令牌数量满足要求,则删除对应数量的令牌并通过当前请求,若桶中令牌数不足则触发限流规则。
为解决固定窗口计数带来的周期切换处流量突发问题,可以使用滑动窗口计数。滑动窗口计算本质上也是固定窗口计数,区别在于将计数周期进行细化。
滑动窗口
滑动窗口计数法与固定窗口计数法相比较,除了计数周期 T 及周期内最大访问(调用)数 N 两个参数,增加一个参数 M,用于设置周期 T 内的滑动窗口数。
数据访问层
最后
本人也收藏了一份Java面试核心知识点来应付面试,借着这次机会可以送给我的读者朋友们
目录:
Java面试核心知识点
一共有30个专题,足够读者朋友们应付面试啦,也节省朋友们去到处搜刮资料自己整理的时间!
Java面试核心知识点
已经有读者朋友靠着这一份Java面试知识点指导拿到不错的offer了
数据访问层
最后
本人也收藏了一份Java面试核心知识点来应付面试,借着这次机会可以送给我的读者朋友们
目录:
[外链图片转存中…(img-GgHTKczm-1714491042375)]
Java面试核心知识点
一共有30个专题,足够读者朋友们应付面试啦,也节省朋友们去到处搜刮资料自己整理的时间!
[外链图片转存中…(img-tyGRVohi-1714491042376)]
Java面试核心知识点
已经有读者朋友靠着这一份Java面试知识点指导拿到不错的offer了
[外链图片转存中…(img-AnarqfV5-1714491042376)]