第九周课后练习
作业一
(至少完成一个)
请简述 JVM 垃圾回收原理。
设计一个秒杀系统,主要的挑战和问题有哪些?核心的架构方案或者思路有哪些?
请简述 JVM 垃圾回收原理
如果 Web 应用运行在 JVM 等具有垃圾回收功能的环境中,那么垃圾回收可能会对系统的性能特性产生巨大影响。理解垃圾回收原理有助于程序优化和参数调优,以及编写内存安全的代码。
以 JVM 为例,其内存主要可划分为堆(heap)和堆栈(stack)。堆栈用户存储线程上下文信息,如方法参数、局部变量等。堆则是存储对象的内存空间,对象的创建和释放、垃圾回收就在这里进行。通过对对象生命周期的观察,发现大部分对象的生命周期都极其短暂,这部分对象产生的垃圾应该被更快地收集,以释放内存,这就是 JVM 分代垃圾回收,其基本原理如图:
Young Generation: Eden Space | From | To-----
Old Generation: <--|
在 JVM 分代垃圾回收机制中,将应用程序可用的堆空间分为年轻代(Young Generation)和老年代(Old Generation),又将年轻代分为:Eden 区(Eden Space)、From 区和 To 区。
新建对象总是在 Eden 区中被创建,当 Eden 区空间已满,就触发一次 Young GC(Garbage Collection,垃圾回收),将还被使用的对象复制到 From 区,这样整个 Eden 区都是未被使用的空间,可供继续创建对象,当 Eden 区再次用完,再触发一次 Young GC,将 Eden 区和 From 区还在被使用的对象复制到 To 区,下一次 Young GC 则是将 Eden 区和 To 区还被使用的对象复制到 From 区。
因此,经过多次 Young GC,某些对象会在 From 区和 To 区多次复制,如果超过某个阈值对象还未被释放,则将该对象复制到 Old Generation。如果 Old Generation 空间也已用完,那么就会触发 Full GC,即所谓的全量回收,全量回收会对系统性能产生较大影响,因此应根据系统业务特点和对象生命周期,合理设置 Young Generation 和 Old Generation 大小,尽量减少 Full GC。
事实上,某些 Web 应用在整个运行期间可以做到从不进行 Full GC。
秒杀系统
设计一个秒杀系统,主要的挑战和问题有哪些?核心的架构方案或者思路有哪些?
下面从三个方面回答这个问题:
概念-问题-解决
秒杀是电子商务网站常见的一种营销手段:将少量商品(通常只有一件)以极低的价格,在特定的时间点出售。比如一元钱的手机,五元钱的电脑,十元钱的汽车等。因为商品价格诱人,而且数量有限,所以很多人趋之若鹜,在秒杀前涌入网站,等到秒杀活动开始的一瞬间,点下购买按钮(在此前购买按钮为灰色,不可以点击)抢购商品。这些商品因为在活动开始后一秒内就被卖光了,所以被称为秒杀。
秒杀虽然对网站推广有很多好处,也能给消费者带来利益,但是对网站技术却是很大的挑战:网站是为正常运营设计的,而秒杀活动带来的并发访问用户却是平时的数百倍甚至上千倍。网站如果为秒杀时的最高访问量设计部署,就需要比正常运营多得多的服务器,而这些服务器绝大多数的时候是用不着的,浪费惊人。
所以网站秒杀业务不能使用网站正常的业务流程,也不能和正常的网站交易共用服务器,必须设计部署专门的秒杀系统,进行专门应对。
1. 秒杀活动的技术挑战
假设某网站的秒杀活动只推出一件商品,预计会吸引 1 万人参加活动,也就是说最大并发请求数是 10000,那么秒杀系统需要应对的技术挑战有如下几点:
对现有网站业务造成冲击
秒杀活动只是网站营销的一个附加活动,这个活动具有时间短,并发访问量大的特点,如果和网站原有应用部署在一起,必然会对现有业务造成冲击,稍有不慎可能导致整个网站瘫痪。
高并发下的应用、数据库负载
用户在秒杀前,通过不断刷新浏览器以保证不会错过秒杀,这些请求如果按照一般的网站应用架构,访问应用服务器、连接数据库,会对应用服务器和数据库服务器造成极大的负载压力。
突然增加的网络及服务器带宽
假设商品页面大小 200K(主要是商品图片大小),那么需要的网络和服务器带宽是 2G(200K*1000),这些网络带宽是因为秒杀活动新增的,超过网站平时使用的带宽。
直接下单
秒杀的游戏规则是到了秒杀时间才能对商品下单购买,在此时间点之前,只能浏览商品信息,不能下单。而下单页面也是一个普通的 URL,如果得到这个 URL,不用等到秒杀开始就可以下单了。
2. 秒杀系统的应对思路
为了应对上述挑战,秒杀系统的应对策略有以下几点:
秒杀系统独立部署
隔离:为了避免因为秒杀活动的高并发访问而拖垮整个网站,使网站不必面对蜂拥而来的用户访问,可将秒杀系统独立部署;如果需要,还可以使用独立的域名,使其与网站完全隔离,即使秒杀系统崩溃了,也不会对网站造成任何影响。
秒杀商品页面静态化
静态化:重新设计秒杀商品页面,不使用网站原来的商品详细页面,页面内容静态化;将商品描述、商品参数、成交记录和用户评价等全部写入一个静态页面,用户请求不需要经过应用服务器和业务逻辑处理,也不需要访问数据库。所以秒杀商品服务不需要部署动态的 Web 服务器和数据库服务器。
租借秒杀活动网络带宽
增加带宽:因为秒杀新增的网络带宽,必须和网络运营商重新购买或租借。为了减轻网站服务器的压力,需要将秒杀商品页面缓存在 CDN,同样需要和 CDN 服务商临时租借新增的出口带宽。
动态生成随机下单页面 URL
动态化 URL:为了避免用户直接访问下单页 URL,需要将该 URL 动态化,即使秒杀系统开发者也无法在秒杀系统开始前访问下单页面的 URL。办法是在下单页面 URL 加入由服务器端生成的随机数作为参数,在秒杀开始的时候才能得到。
3. 核心架构方案
基于上述策略,秒杀系统首先尽可能简单的设计页面。
商品页面中的购买按钮只有在秒杀活动开始的时候才变亮,在此之前及秒杀商品卖光了之后,该按钮都是灰色的,不可以点击。
下单表单也尽可能简单,购买数量只能是一个且不可以修改,送货地址和付款方式都是使用用户默认设置的,没有默认也可以不填,允许下单成功后再修改。
除了上面提到的问题,还有一些问题需要处理:
如何控制秒杀商品页面购买按钮点亮?
购买页面可以在服务器构造输出,控制该按钮是灰色还是点亮,但是为了减轻服务器端的负载压力,更好的利用 CDN、反向代理等性能优化手段,该页面被设计为静态页面,缓存在 CDN、反向代理服务器上,甚至用户的浏览器上。秒杀开始时,用户刷新页面,用户请求根本不会到达应用服务器。
解决办法是使用 JavaScript 脚本控制,在秒杀静态商品页面加入一个 JavaScript 文件引用,该 JavaScript 文件中加入秒杀是否开始的标志和下单页面 URL 的随机参数,当秒杀开始的时候生成一个新的 JavaScript 文件并被用户浏览器加载,控制秒杀商品的展示。这个 JavaScript 文件使用随机版本号,并且不被浏览器、CDN 和反向代理服务器缓存。
这个文件特别小,即使每次刷新访问也不会对服务器集群和网络带宽造成太大压力。
只允许少数的订单成功。
由于只有少数用户能够秒杀成功,因此可以在用户点击购买的时候使用计数器,例如 1000,如果超过了 1000,直接提示用户秒杀结束。然后进入下单页面,判断用户下单是否超过了例如:56,即提示用户秒杀结束,那么通过拦截,只有 56 个用户能够下单成功,减轻的服务器压力。
4. 总述
老师在课程中有其它优化项,但是都是基于核心的策略进行的扩展,在一个较短时间内,例如 5 天时间,这个方案是基础。
万能页面:秒杀活动是对网站架构极大的考验,在难以预计和控制的高并发访问冲击下,稍有不慎,系统就会被用户秒杀,导致整个系统宕机,活动失败,造成重大事故。因此在遵循秒杀活动规则的基础上,为了保证系统的安全,保持适度的公平公正即可。即使系统出了故障,也不应该给用户显示出错页面,而是显示秒杀活动结束页面,避免不必要的困扰。
致谢:参考老师的《大型网站技术架构》。
评论