系统过载及其危害

系统过载就是当前负载已经超过了系统的最大处理能力。例如,系统每秒能够处理的请求是100个,但实际每秒的请求量却是1000个,就可以判定系统出现了过载。

通常可以用QPS、请求处理的平均时延等去评估系统处理能力,系统瓶颈指系统中最先接近极限的资源,一般系统资源包括CPU,内存,IO。

过载的出现,会导致部分服务不可用,如果处置不当,极有可能引起服务完全不可用,乃至雪崩。

如何进行过载保护

如何进行过载保护,有如下一些策略:

1. 做好容量规划 & 线性扩容(能支持弹性扩缩容最好)

最简单也是最基本的,在系统部署上线之前,要预估好线上请求的峰值,预估好系统的处理能力,留有一定的buffer。另外,系统要能够支持线性扩容(核心关键是无状态化)。当然 k8s + docker 的辅助下,现在做到弹性扩缩容也不是一件可望不可及的技术了。那么相对会简单很多,不过做好基本的容量规划还是必须的,有时候来不及扩容就直接被压垮了。

2. 及早拒绝:前端保护后端,后端不信任前端

前端系统有保护后端系统的义务,sla中承诺多大的能力,就只给到后端多大的压力。这就要求每一个前后端接口的地方,都有明确的负载约定,一环扣一环。

同时每个系统要做好自我保护,量力而为,而不是尽力而为。当后端发现自己超过负载能力时,也要有机制拒绝前端发来的新增请求,对于超出自己处理能力范围的请求,要勇于拒绝,熔断降级。

3. 频率限制(限流)

可以通过设置一定的频率限制,控制接口的请求频率。防止过载请求,特别是恶意攻击。

常见的限流算法有:计数器、漏桶和令牌桶算法。

4. 黑白名单

将请求频率过高的来源加入黑名单中,是一种简单快速的过载保护机制。

5. 轻重分离,影响面控制在最小

轻重分离的主旨是对服务的内容进行细分,按照高内聚低耦合的方式部署服务,使得局部的过载不扩散到整个系统。

常规的分离方法:

  • 渠道分离:如有线、无线服务的分离;
  • 部署分离:如电信、联通、教育、海外服务的分离;
  • 快慢分离:如文字、图片、视频、下载等服务的分离;
  • 用户分离:按set划分系统为用户提供服务,常用的方式是按游戏世界(互娱)、按UIN号段、按UIN取模等方式做到服务的逻辑直至物理的隔离;

6. 阀门和限流: 抽奖,秒杀

对于抽奖和秒杀这种特殊的业务场景,可以采用阀门和限流来避免过载。因为像这种业务场景不需要考虑公平性,而且用户下单的概率极大。所以对于这种场景,最简单有效的方式就是设置阀门,只放跟秒杀商品/奖品数量差不多的人进入秒杀/抽奖系统。比如在电商的秒杀系统中,可以设置三道阀门,形成如下漏斗型的流量限制:

  • 限制进入秒杀页面:1000个
  • 限制进入下单页面:100个
  • 限制进入支付系统:56个

Alt text

通过一层层的阀门限流,就把巨大的抢购流量削减为很轻量级的流量了,跟平时正常下单也没有啥区别了,系统自然不会过载。

Alt text

7. 排队异步化:抢票,秒杀,支付

另一种有效的过载保护策略是排队,把同步等待变成异步处理通知。消息队列是最常见的排队手段,可以起到削峰的作用。比如12306的抢票,微信红包入账等,都是这种策略。

Alt text

8. 产品策略优化

最后,除了以上技术手段,还可以从产品策略上进行防护。下面举几个真实的例子说明。

有一年的淘宝双十一,用户在最后支付的时候因为支付宝余额不足跳转第三方银行支付系统,而对方的支付系统根本应对不了这么大的并发量直接奔溃,导致大量的下单失败。

因为是第三方的支付系统,淘宝没办法要求对方提升SLA。最后想了一个方案,在双十一之前,通过优惠等方式鼓励用户提前在支付宝预充余额。这样双十一当天下单的时候就直接在支付宝系统搞定了,不需要调到第三方银行支付接口,简单完美的避过了这个外界短板。后面还出了一个策略,让用户预先将要购买的商品放入购物车,到双十一当天支付就可以享受双十一的价格,也是一种产品策略上的错峰。

另外,在产品交互设计上要做好置灰和提示,避免用户不断刷新重试,增加无效负载。都是简单有效的过载保护。

Alt text