限流器用于控制在网络上发送或接收的流量速率。限流器对于大部分使用场景是十分高效的,但有时我们需要完全丢弃低优先级的请求,以确保更多关键请求的处理,这称为负载降级(load shedder)。负载降级可以根据系统的整体状态而不是正在请求的用户来进行决策。它可以帮助我们应对突发事件,确保核心部分正常工作。
请求限流器
该限流器限制每个用户每秒可发送 N 个请求。
并发请求限流器
相对于第一种请求限流器,限制每秒最高请求数,这种限流器则是限制最高并发请求数。有些 API endpoint 对外部资源依赖多,用户经常处于请求-等待返回-重试。这些重试继续加剧了已经超载的服务。并发请求限流器有助于很好地解决这个问题。
基于使用量的负载降级
我们将流量分为两种类型:关键 API 请求(例如,创建订单)和非关键请求(例如,列出历史订单)。我们总是为关键请求预留一小部分冗余。例如,我们的预留比例是20%,那么超过 80% 的非关键请求将被拒绝服务,并返回503的状态码。
基于 Worker 利用率的负载降级
大多数 API 服务使用一组 worker 线程/协程以并行方式独立地处理请求并响应。 这种负载降级是最后的防线。
我们将流量分为4类组成:
-
关键 API 请求
-
HTTP POST 方法
-
HTTP GET 方法
-
测试请求
我们追踪可用的 worker 数量。如果某个 worker 太忙,无法处理分配给它的请求,它会缓慢降级非关键请求,当然是先从测试请求开始。如果降低测试请求的过程中,worker 的处理能力恢复到好的状态,那我们就可以开始缓慢地恢复流量(取消降级)。
缓慢地进行降级和恢复是非常重要的!比如这个场景:“我完全丢弃了测试请求的流量,一切都很好!我把它恢复回来,噢一切又变糟了!”。我们用了大量的尝试和错误来调整降级和恢复的速率。
这种负载降级限制了已经发生事件的影响,控制了近一步的损害,比如你们知道的“雪崩效应”。