• 接口级故障的典型表现就是系统并没有宕机,网络也没有中断,但业务却出现了问题。例
    如,业务响应缓慢、大量访问超时、大量访问出现异常(给用户弹出提示“无法连接数据
    库”),这类问题的主要原因在于系统压力过大、负载太高,导致无法快速处理业务请求,
    由此引发更多的后续问题。例如,最常见的数据库慢查询将数据库的服务器资源耗尽,导致
    读写超时,业务读写数据库时要么无法连接数据库、要么超时,最终用户看到的现象就是访
    问很慢,一会访问抛出异常,一会访问又是正常结果。

导致接口级故障的原因一般有下面几种:

内部原因

  • 程序 bug 导致死循环,某个接口导致数据库慢查询,程序逻辑不完善导致耗尽内存等。

外部原因

  • 黑客攻击、促销或者抢购引入了超出平时几倍甚至几十倍的用户,第三方系统大量请求,第
    三方系统响应缓慢等。

解决接口级故障的核心思想

  • 优先保证核心业务和优先保证绝大部分用户

降级

  • 降级指系统将某些业务或者接口的功能降低,可以是只提供部分功能,也可以是完全停掉所
    有功能。例如,论坛可以降级为只能看帖子,不能发帖子;也可以降级为只能看帖子和评
    论,不能发评论;而 App 的日志上传接口,可以完全停掉一段时间,这段时间内 App 都
    不能上传日志。

  • 降级的核心思想就是丢车保帅,优先保证核心业务。例如,对于论坛来说,90% 的流量是
    看帖子,那我们就优先保证看帖的功能;对于一个 App 来说,日志上传接口只是一个辅助
    的功能,故障时完全可以停掉。

  • 常见的实现降级的方式有:
    简单来说,就是系统预留了后门用于降级操作。例如,系统提供一个降级 URL,当访问这
    个 URL 时,就相当于执行降级指令,具体的降级指令通过 URL 的参数传入即可。这种方
    案有一定的安全隐患,所以也会在 URL 中加入密码这类安全措施。
    系统后门降级的方式实现成本低,但主要缺点是如果服务器数量多,需要一台一台去操作,
    效率比较低,这在故障处理争分夺秒的场景下是比较浪费时间的。

熔断

  • 熔断和降级是两个比较容易混淆的概念,因为单纯从名字上看好像都有禁止某个功能的意
    思,但其实内在含义是不同的,原因在于降级的目的是应对系统自身的故障,而熔断的目的
    是应对依赖的外部系统故障的情况。

  • 假设一个这样的场景:A 服务的 X 功能依赖 B 服务的某个接口,当 B 服务的接口响应很慢
    的时候,A 服务的 X 功能响应肯定也会被拖慢,进一步导致 A 服务的线程都被卡在 X 功能
    处理上,此时 A 服务的其他功能都会被卡住或者响应非常慢。这时就需要熔断机制了,
    即:A 服务不再请求 B 服务的这个接口,A 服务内部只要发现是请求 B 服务的这个接口就
    立即返回错误,从而避免 A 服务整个被拖慢甚至拖死。

  • 熔断机制实现的关键是需要有一个统一的 API 调用层,由 API 调用层来进行采样或者统
    计,如果接口调用散落在代码各处就没法进行统一处理了。

  • 熔断机制实现的另外一个关键是阈值的设计,例如 1 分钟内 30% 的请求响应时间超过 1
    秒就熔断,这个策略中的“1 分钟”“30%”“1 秒”都对最终的熔断效果有影响。

限流

  • 降级是从系统功能优先级的角度考虑如何应对故障,而限流则是从用户访问压力的角度来考
    虑如何应对故障。限流指只允许系统能够承受的访问量进来,超出系统访问能力的请求将被
    丢弃。

  • 虽然“丢弃”这个词听起来让人不太舒服,但保证一部分请求能够正常响应,总比全部请求
    都不能响应要好得多。

  • 限流一般都是系统内实现的,常见的限流方式可以分为两类:基于请求限流和基于资源限
    流。

  • 基于请求限流指从外部访问的请求角度考虑限流,常见的方式有:限制总量、限制时间量。
    限制总量的方式是限制某个指标的累积上限,常见的是限制当前系统服务的用户总量,例如
    某个直播间限制总用户数上限为 100 万,超过 100 万后新的用户无法进入;某个抢购活动
    商品数量只有 100 个,限制参与抢购的用户上限为 1 万个,1 万以后的用户直接拒绝。限
    制时间量指限制一段时间内某个指标的上限,例如,1 分钟内只允许 10000 个用户访问,
    每秒请求峰值最高为 10 万。

  • 无论是限制总量还是限制时间量,共同的特点都是实现简单,但在实践中面临的主要问题是
    比较难以找到合适的阈值,例如系统设定了 1 分钟 10000 个用户,但实际上 6000 个用户
    的时候系统就扛不住了;也可能达到 1 分钟 10000 用户后,其实系统压力还不大,但此时
    已经开始丢弃用户访问了。

  • 即使找到了合适的阈值,基于请求限流还面临硬件相关的问题。例如一台 32 核的机器和
    64 核的机器处理能力差别很大,阈值是不同的,可能有的技术人员以为简单根据硬件指标
    进行数学运算就可以得出来,实际上这样是不可行的,64 核的机器比 32 核的机器,业务
    处理性能并不是 2 倍的关系,可能是 1.5 倍,甚至可能是 1.1 倍。

  • 为了找到合理的阈值,通常情况下可以采用性能压测来确定阈值,但性能压测也存在覆盖场
    景有限的问题,可能出现某个性能压测没有覆盖的功能导致系统压力很大;另外一种方式是
    基于请求限流
    限制总量的方式是限制某个指标的累积上限,常见的是限制当前系统服务的用户总量,例如
    某个直播间限制总用户数上限为 100 万,超过 100 万后新的用户无法进入;某个抢购活动
    商品数量只有 100 个,限制参与抢购的用户上限为 1 万个,1 万以后的用户直接拒绝。限
    制时间量指限制一段时间内某个指标的上限,例如,1 分钟内只允许 10000 个用户访问,
    每秒请求峰值最高为 10 万。

排队

  • 排队实际上是限流的一个变种,限流是直接拒绝用户,排队是让用户等待一段时间,全世界
    最有名的排队当属 12306 网站排队了。排队虽然没有直接拒绝用户,但用户等了很长时间
    后进入系统,体验并不一定比限流好。
  • 由于排队需要临时缓存大量的业务请求,单个系统内部无法缓存这么多数据,一般情况下,
    排队需要用独立的系统去实现。