关于过载保护的一些思考

766 阅读5分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

什么是过载

我们先来理解下,什么是过载?我理解中的过载就是请求数量太高,超过了服务器的处理能力,然后造成了请求的积压;然后如果请求还在源源不断的过来,那么就会导致缓存区的请求堆积的越来越多,最后所有的请求都按照超时处理,造成系统的瘫痪。

过载现象及原因分析

造成系统过载的原因我们也可以从两方面来分析,第一请求数太多,第二,服务端太差,处理能力不行。

针对于第一点过多的请求,可能是因为我们做的产品太牛逼了,用户激增导致;当然更多情况下是因为我们的设计出现了问题,比如说我们的重试策略有问题,频繁触发重试,导致重试风暴,加重了系统的负担;比如说我们产品设计不合理,引导用户重试,造成用户的频繁点击等等

针对第二点服务端太差了,比如说代码占用大量内存,内存不足又会使用swap分区写磁盘,最终导致系统的CPU负载过高。

处理方式

所以说从处理方式上我们也从两点来考虑,

  1. 从请求数太多出发,我们可以采取一些限流方案,比如说计数器算法,滑动窗口算法,漏桶算法,令牌桶算法:

    1. 计数器算法:

      1. 在一定的时间间隔内,记录请求次数,当请求次数超过该时间间隔时,就把计数器清零,然后重新计算,如果请求次数超过间隔内的最大次数,则拒绝访问。
      2. 缺点:如果在两个间隔之间有密集的请求,则会导致单位时间内的实际请求数量超过阈值:比如当在时间临界点的时候比如0:59分,瞬间来了100个请求,这个时候能够正常处理请求,但是在1:01的时候,又来了100个请求,这个时候也能正常处理请求,但是在2s内,一共处理了200个请求,可能会造成后端过载。
    2. 滑动窗口算法

      1. 一个时间窗口为1分钟,滑动窗口分为10个格子,每个格子6s中
      2. 每过6s,滑动窗口向右滑动一个格子
      3. 每个格子都有独立的计数器
      4. 如果时间窗口内的所有计数器纸之和超过限流阈值,则触发拒绝操作
    3. 漏桶算法:桶的底部有个洞,当装上水的时候,水会一滴滴的从底部漏掉,当装水太满时,水会溢出来,但底部漏水的速度还是不变的。

      1. 底部漏水的速度就是系统处理的速度,桶里存储的水就是上游过来的请求。当请求太多,超过桶的容量时,就会被拒绝

      2. 使用场景:

        1. 在系统启动时,如果想让系统有一个陆续启动的过程,则不要一下子接受太多的请求,让系统处理的请求量平缓上升到最大处理能力
        2. 系统可以在一些时刻处理突增的请求,只要持续时间不是很长,系统有能力处理即可
    4. 令牌桶算法:以一个固定的速率往一个桶中增加令牌,当桶中的令牌满了之后,就停止增加令牌。上游请求时,先从桶里拿一个令牌,后端只服务有令牌的请求,所以后端的处理速度不是均速的,当有突发请求过来时,如果令牌桶是满的,则会瞬间消耗桶中的存量的令牌。如果还不够,就只能等待系统均速发放令牌了。

  2. 为了防止用户的重复点击我们可以从防抖方向处理,比如说用户3s内只能点击1次;避免无效的请求我们可以从节流方向考虑,比如说用户输入验证码我们验证有效性,我们可以规定好验证码的长度,必须是这么长的验证码,我们才会向服务端发出请求;

  3. 针对于服务端过载过高,我们可以监控CPU的资源,当CPU的资源过高时,我们自动横向扩展服务器,提高服务器的处理能力

  4. 为了避免重试风暴,需要我们设置一种重试策略,比如说第一次请求1s内,第二次请求2s后,第三次请求5s后逐渐拉开间距,并设置最高的重试次数,避免无脑重试;

  5. 要有降级熔断处理;优雅的降级熔断方案,避免影响用户的体验;

  6. 尽早拒绝,尽早丢弃掉一定会超时的请求,另外对于调用链维度,我们要保证调用链路的请求是完整的,不能A调用链路丢弃一部分,B调用链路丢弃一部分,那样可能会导致每个请求都是失败的;

  7. 对服务访问设置优先级,比如说下单的优先级要高于查看商品评价的优先级;服务器资源不足的时候,对商品评价服务进行降级处理;

  8. 注意业务的隔离,线程池的隔离,主次业务的隔离等等