關於服務限流這回事,總算整明白了

2023.02.28

關於服務限流這回事,總算整明白了


本文從宏觀角度總結了服務限流的兩種方式,三個可以限流的位置,四種常見的限流算法,五種限流的策略。最後再補充幾句,合理的限流配置,需要了解系統的吞吐量,所以,限流一般需要結合容量規劃和壓測來進行。

​前言

隨著現在微服務、分佈式系統的發展,各個服務之間的相互調用越來越複雜。為了保證自身服務的穩定性與高可用,當面對超過自身服務能力的請求調用時,要做一定的限流措施。如同五一、國慶期間的旅遊出行、景區爆滿,遊客限流。我們的服務面對諸如秒殺、大促、618、雙十一以及可能的惡意攻擊、爬蟲等高並發、大流量的場景也需要做服務限流。

对超出服务处理能力之外的请求进行拦截,对访问服务的流量进行限制,这就是服务限流。接下来我们就好好谈谈服务限流这回事儿。

两种限流方式

常见的限流方式可以分为两类:基于请求限流和基于资源限流。

  1. 基于请求限流

基于请求限流指从外部访问的请求角度考虑限流,常见的方式有两种。

第一种是限制总量,也就是限制某个指标的累积上限,常见的是限制当前系统服务的用户总量,例如:某个直播间限制总用户数上限为100万,超过100万后新的用户无法进入;某个抢购活动商品数量只有100个,限制参与抢购的用户上限为1万个,1万以后的用户直接拒绝。

第二种是限制时间量,也就是限制一段时间内某个指标的上限,例如1分钟内只允许10000个用户访问;每秒请求峰值最高为10万。

优点:

  • 实现简单

缺点:

  • 实践中面临的主要问题是比较难以找到合适的阈值。例如系统设定了1分钟10000个用户,但实际上6000个用户的时候系统就扛不住了;或者达到1分钟10000用户后,其实系统压力还不大,但此时已经开始丢弃用户访问了。而且还要考虑硬件相关的因素,例如一台32核的机器和64核的机器处理能力差别很大,阈值是不同的。

应用:

  • 适用于业务功能比较简单的系统,例如负载均衡系统、网关系统、抢购系统等。
  1. 基于资源限流

基于请求限流是从系统外部考虑的,而基于资源限流是从系统内部考虑的,也就是找到系统内部影响性能的关键资源,对其使用上限进行限制。常见的内部资源包括连接数、文件句柄、线程数和请求队列等。比如CPU的占用率超过80%的时候就开始拒绝新的请求。

优点:

  • 有效地反映当前系统的压力,更好的进行限流

缺点:

  • 难以确定关键资源
  • 难以确定关键资源的阈值,需要在线上逐步调试,持续观察,直到找到合适的值。

应用:

  • 适用于具体的某个服务,比如订单系统、商品系统等。

四种限流算法

常见的限流算法有4种,它们的实现原理和优缺点各不相同,在实际设计的时候需要根据业务场景来选择。

  1. 固定时间窗

固定时间窗算法的实现原理是,统计固定时间周期内的请求量或者资源消耗量,超过限额就会启动限流,如下图所示:

圖片

优点:

  • 实现简单

缺点:

  • 存在临界点问题。例如上图中的红蓝两点只间隔了短短10秒,期间的请求数却已经达到200,超过了算法规定的限额(1分钟内处理100)。但是因为这些请求分别来自两个统计窗口,从单个窗口来看还没有超出限额,所以并不会启动限流,结果可能导致系统因为压力过大而挂掉。
  1. 滑动时间窗

为了解决临界点问题,滑动时间窗算法应运而生,它的实现原理是,两个统计周期部分重叠,从而避免短时间内的两个统计点分属不同的时间窗的情况,如下图所示:

圖片

优点:

  • 不存在临界点问题

缺点:

  • 相对于固定窗口,复杂度有所提升
  1. 漏桶算法

漏桶算法的实现原理是,将请求放入“桶”(消息队列等),业务处理单元(线程、进程和应用等)从桶里拿请求处理,桶满则丢弃新的请求,如下图所示:

圖片

优点:

  • 突发大量流量时丢弃的请求较少,因为漏桶本身有缓存请求的作用

缺点:

  • 可以平滑流量,但是无法解决流量突增的问题。
  • 桶大小动态调整比较困难,需要不断的尝试才能找到符合业务需求的最佳桶大小。
  • 无法精确控制流出速度,也就是业务的处理速度。

漏桶算法主要适用于瞬时高并发流量的场景(例如刚才提到的0点签到、整点秒杀等)。在短短几分钟内涌入大量请求时,为了更好的业务效果和用户体验,即使处理慢一些,也要做到尽量不丢弃用户请求。

  1. 令牌桶算法

令牌桶算法和漏桶算法的不同之处在于,桶中放入的不是请求,而是“令牌”,这个令牌就是业务处理前需要拿到的“许可证”。也就是说,当系统收到一个请求时,先要到令牌桶里面拿“令牌”,拿到令牌才能进一步处理,拿不到就要丢弃请求。

它的实现原理是如下图所示:

圖片

优点:

  • 通过控制放入令牌的速率,可以动态调整处理速率,实现更加灵活。
  • 可以平滑限流,同时可以容忍突发流量,因为桶里面可以累积一定数量的令牌,当突发流量过来的时候,桶里面有累积的令牌,此时的业务处理速度会超过令牌放入的速度。

缺点:

  • 突发大量流量的时候可能丢弃很多请求,因为令牌桶不能累积太多令牌。
  • 实现相对复杂。

令牌桶算法主要適用於兩種典型的場景,一種是需要控制訪問第三方服務的速度,防止把下游壓垮,例如支付寶需要控制訪問銀行接口的速率;另一種是需要控制自己的處理速度,防止過載,例如壓測結果顯示系統最大處理TPS是100,那麼就可以用令牌桶來限制最大的處理速度。

五種限流策略

  1. 服務拒絕

當請求流量達到限流閾值時,對多餘的請求直接拒絕。

可通過設計實現對指定域名、IP、客戶端、應用、用戶等不同來源的請求進行拒絕。

  1. 延時處理

通過將多餘的請求加入緩存隊列或延時隊列,來應對短期的流量突增,高峰期過後開始將堆積的請求流量逐漸處理。

  1. 請求分級(優先級)

對不同來源的請求設置優先級,先處理優先級更高的請求。如VIP客戶、重要的業務應用(如交易服務優先級高於日誌服務)。

  1. 動態限流

可以監控系統相關指標、評估系統壓力,通過註冊中心、配置中心等動態調整限流閾值。

  1. 監控預警&動態擴容

如果有優秀的服務監控系統與自動部署、發布系統,可以通過監控系統自動監測系統運行情況,對短期內服務壓力暴增、流量大幅寫入的情況進行郵件、短信等方式進行預警。

在滿足特定條件下,可自動部署、發布相關服務,起到動態擴容的效果。

三個限流位置

  1. 接入層限流

可以通過Nginx、API路由網關等對域名或IP進行限流,同時可以攔截非法請求。

  1. 應用限流

每個服務可以有自己的單機或集群限流措施,也可以調用第三方的限流服務,比如阿里的Sentinel限流框架。

  1. 基礎服務限流

也可以對基礎服務層進行限流。

  • 數據庫:限制數據庫連接、限制讀寫速率
  • 消息隊列:限制消費速率(消費量、消費線程)

總結

本文從宏觀角度總結了服務限流的兩種方式,三個可以限流的位置,四種常見的限流算法,五種限流的策略。最後再補充幾句,合理的限流配置,需要了解系統的吞吐量,所以,限流一般需要結合容量規劃和壓測來進行。當外部請求接近或者達到系統的最大閾值時,觸發限流,採取其他的手段進行降級,保護系統不被壓垮。