降级 限流 熔断

272 阅读4分钟

常见容错机制:failover、failfast、failback、failsafe

failover:失效转移 当主要组件异常时,其功能转移到备份组件。

failfast:快速失败(不持续等待)

failback:失效自动恢复

failsafe:失效安全 即使在故障的情况下也不会造成伤害或者尽量减少伤害

  • 一些熔断组件会实现这些功能

服务降级怎么做

cloud.tencent.com/developer/a…

保证核心服务可用;非核心服务弱可用,甚至不可用

  • 核心服务:直接和钱沾边,或者间接和钱沾边
    • 购物车、支付 等
  • 非核心服务:和钱不沾边,或者不影响支付
    • 我的订单、退货服务 等

服务降级手段

拒绝部分请求(限流)

关闭部分业务(业务相关)

服务层降级架构层次

  • 集中式

    • 网关层
  • 自治式

    • 业务逻辑层
    • 数据访问层 因为不同的层次的同样设备的处理能力是不一样的,假设网关层能处理200请求,业务逻辑层只能处理100请求,数据访问层,只能处理50请求

集中式:

直接在网关层砍掉150请求才能符合数据访问层的请求能力,并且是中间隔着业务逻辑层的,并不好知道

自治式:

层层降级,最终砍到数据访问层能处理的请求数量,因为每层都是挨着的所以,容易一些

数据层降级

  • 更新请求

    • 持久到消息队列
    • 只更新缓存
  • 读请求

    • 读缓存
  • 数据补齐

    • 消息队列->[数据库]

新浪微博,在数据流量的高峰期,比如网红发段子,或者一些事件,那么更新的消息数据会写到队列中并写入缓存,其他人拉取的时候,都是读取的缓存,等到流量陷入低峰期时,读取消息队列,并写入到数据库,实现数据补齐

限流、熔断

服务雪崩

当 “服务C” 出现问题时,可能是宕机,上线出 bug,流量过大或缓存穿透数据库压垮服务,这时“服务 C”响应就会出问题,而“服务 B”由于拿不到响应结果又会不断重试进一步压垮“服务 C”,同时“服务 B”同步调用也会有大量等待线程,出现资源耗尽,导致“服务 B”变得不可用,进而影响到“服务 A”,形成雪崩效应。

image.png

image.png 上游服务做限流,下游服务做熔断

限流算法

zhuanlan.zhihu.com/p/376564740

固定窗口限流算法

首先维护一个计数器,将单位时间段当做一个窗口,计数器记录这个窗口接收请求的次数。

  • 当次数少于限流阀值,就允许访问,并且计数器+1
  • 当次数大于限流阀值,就拒绝访问。
  • 当前的时间窗口过去之后,计数器清零。 伪代码如下:
    boolean fixedWindowsTryAcquire() {
        long currentTime = System.currentTimeMillis();  //获取系统当前时间
        if (currentTime - lastRequestTime > windowUnit) {  //检查是否在时间窗口内
            counter = 0;  // 计数器清0
            lastRequestTime = currentTime;  //开启新的时间窗口
        }
        if (counter < threshold) {  // 小于阀值
            counter++;  //计数器加1
            return true;
        }

        return false;
    }

临界问题

滑动窗口限流算法

滑动窗口限流解决固定窗口临界值的问题。它将单位时间周期分为n个小周期,分别记录每个小周期内接口的访问次数,并且根据时间滑动删除过期的小周期。

并没有真正解决临界突发流量问题。 一旦到达限流后,请求都会被暴力拒绝。

漏桶算法

1.容量限制:漏桶有一个固定的容量,一旦达到容量,进入的额外数据会被丢弃 2.恒定流出速率:数据以固定的速率从桶中流出。 3.流入速率可变:数据可以以任意速率流入桶内。

令牌桶算法

  • 系统根据限流大小,定速往令牌桶里放令牌。
  • 如果令牌数量满了,超过令牌桶容量的限制,那就丢弃。
  • 系统在接受到一个用户请求时,都会先去令牌桶要一个令牌。如果拿到令牌,那么就处理这个请求的业务逻辑;
  • 如果拿不到令牌,就直接拒绝这个请求。

这种算法允许的最大并发请求量就是令牌桶的容量

熔断

zhuanlan.zhihu.com/p/340660145

image.png

熔断器设计模式是基于 AOP 对所有的请求调用进行拦截,在请求调用前做状态判断是否熔断,请求调用后做计数统计 (记录失败比例),并根据策略做熔断状态转移。

框架

sentinel-golang image.png