为什么要有兜底方案
虽然我们前面设计了很多极致的优化方案,但是现实情况是意外不经意就发生了,这些看似不经意的意外,却有可能带来非常严重的后果。对于秒杀系统,我们需要设定一个兜底方案,保证最坏情况下系统也能正常运行。
兜底方案的设计其实说白了就是为了实现系统的高可用,那么我们平常是如何设计高可用系统的呢?
高可用系统建设
高可用系统的建设贯穿于系统的整个生命周期,包括架构设计阶段、编码阶段、测试阶段、发布阶段、运行阶段,以及故障发生阶段。每个阶段都可能产生问题,如果事先没有考虑到高可用建设方案,那么出现问题时影响的是整个系统。
每个阶段的主要关注点:
1.架构设计阶段:架构设计阶段主要考虑的是系统的可扩展性和容错性,比如避免单点问题。
2.编码阶段:编码阶段主要考虑的是代码的健壮性,比如远程接口调用时,需要设置合理的超时退出机制,防止被其他系统拖垮,也要对返回结果预期范围或者超出预期范围进行相应的处理,例如对无法预料的错误要有异常捕获机制以及默认返回值。
3.测试阶段:测试阶段主要关注的是测试用例的覆盖度,保证最坏情况发生时也会有对应的处理流程。
4.发布阶段:发布阶段主要考虑的是发布错误的一个紧急回滚机制。
5.运行阶段:运行阶段主要考虑的是对系统的一个准确的监控,发现问题能及时的记录并报警,便于问题的排查。
6.故障阶段:故障发生阶段最主要的还是考虑如何减少后续的影响,比如对商品的下架,活动的关闭等,而且要有快速的恢复服务,定位问题并解决问题的能力。
对于秒杀系统,面对大流量时,我们最关注的应该是系统运行阶段的高可用,运行阶段高可用三种手段:降级、限流、拒绝服务。
秒杀高可用系统保障的方式
1.降级:指系统的请求量达到一定程度时,限制或者关闭非核心功能,将有限的资源留给核心业务系统。它的目的是牺牲次要的功能和用户体验保证核心业务流程的稳定。比如商品交易系统,为了保证系统高可用,可以将商品详情的优惠信息展示降级,把有限的资源用于保证交易系统正确展示优惠信息上,保证用户下单价格是正确的。
降级一定是一个有目的、有计划的执行过程,对于降级需要有一套预案来配合执行。如果我们把它系统化,就可以通过预案系统和开关系统来实现降级功能。
开关系统主要分为两部分:
- 开关控制台:保存了具体的开关配置信息,以及具体执行开关的节点列表。
- 执行下发开关数据的agent:保证开关被正确执行,系统重启也能使生效。
可以参考如下的开关系统设计:
2.限流
限流相比于降级的牺牲部分次要功能和用户体验而言,限流是一种更极端的保护措施。当系统请求流量达到瓶颈时,限制一部分流量来保护系统。
限流实现位置:客户端限流、服务端限流。
客户端限流:可以最直接的控制请求数的发出,减少无用请求对服务端系统的消耗。缺点是客户端太分散不太可控,无法设置合理的限流阈值。
服务端限流:可以在服务端根据性能统一设置阈值。缺点是客户端无用的请求还是会请求到服务端,消耗服务器资源。
限流实现手段:限流实现既要支持url级别的限流、方法级别的限流,也要支持基于qps的限流、线程的限流。而基于qps和线程的限流用的最多,因为系统的最大qps可以通过提前压测得之,那么我们可以设置为最大qps*80%的合理请求数来进行系统保护,线程数在客户端可以进行控制,将多余的线程进行排队或者超时处理如丢弃。
注意,限流会导致一部分用户请求失败,而系统处理这种异常时要设置一定的超时时间,防止被限流的请求不能fast fail而拖垮系统。
3.拒绝服务
如果前面两个手段还不能解决问题的话,就采用最后的手段直接拒绝服务。拒绝服务是一种不得已的最终兜底方案,以防最坏请求发生。当系统达到一定的阈值,比如cpu使用率达到90%或者系统load值达到cpu*2核数量时,直接拒绝服务。
今天分享到这里,喜欢我的读者可以骚操作一波【关注】、【点赞】、【转发】,后续有更精彩的内容更新哦。可以在我的头条小程序页面领取自己喜欢的资料或者选择阅读自己喜欢的类型文章。
本文暂时没有评论,来添加一个吧(●'◡'●)