zuul接口限流之spring-cloud-zuul-ratelimit

網上找到的資料大多是針對服務限流,接口限流的資料很少,而且配置複雜,於是我結合網上資料和自己的實踐,去粗取精,形成了適合自己的極簡配置。

導入依賴

<dependency>
  <groupId>com.marcosbarbero.cloud</groupId>
  <artifactId>spring-cloud-zuul-ratelimit</artifactId>
  <version>2.4.0.RELEASE</version>
</dependency>

配置參考 

zuul:
  routes:
    user-web:
      path: /user/**
      serviceId: jd-user-web
      stripPrefix: false
    order-web:
      path: /order/**
      serviceId: jd-order-web
      stripPrefix: false
  ratelimit:
    key-prefix: ${spring.application.name}-rate-limit #緩存key的前綴
    enabled: true #開啓限流
    repository: REDIS #key存儲方式爲redis
    behind-proxy: true # 當前網關是代理後的請求,需要獲取Header中的X-FORWARDED-FOR以便獲取源IP
    policy-list: #指定服務策略,優先默認
      user-web: #路由ID
        - limit: 5 #每個刷新窗口請求數
          quota: 3 #每個刷新窗口總請求時間(秒)
          refresh-interval: 15 #刷新窗口時間(秒),默認60秒
          type:
            - url=/user/getUser
        - limit: 5 #每個刷新窗口請求數
          quota: 3 #每個刷新窗口總請求時間(秒)
          refresh-interval: 15 #刷新窗口時間(秒),默認60秒
          type:
            - url=/user/getWxUser
      order-web:
        - limit: 5 #每個刷新窗口請求數
          quota: 3 #每個刷新窗口總請求時間(秒)
          refresh-interval: 15 #刷新窗口時間(秒),默認60秒
          type:
            - url=/order/shop/list

關鍵參數解讀

以下面參數爲例,進行詳細說明。

user-web: #路由ID

    limit: 5 #每個刷新窗口請求數
    quota: 3 #每個刷新窗口總請求時間(秒)
    refresh-interval: 15 #刷新窗口時間(秒),默認60秒

user-web:此處不是serviceId,網上都是誤導的,我管他叫路由ID,如果serviceId和路由ID不一致,此次要取路由ID,否則,會導致限流不起作用。

limit: 請求總次數。15秒內只能請求5次,超過了報 "429 TOO_MANY_REQUESTS"。
quota: 請求累計時長。每次請求的時間,累計不能超過3秒,假如前4次請求總耗時已經超過3秒,那麼第5次請求報"429 TOO_MANY_REQUESTS"。這個參數一般可以省略。
refresh-interval: 統計請求的時間窗口長度。從第一次請求開始,在緩存裏設置一個15秒後失效的key,key由key-prefix + routeId + url拼接成。
如果在第5秒的時候,請求超過了5次,那麼後續請求都報"429 TOO_MANY_REQUESTS",只能繼續等待10秒緩存失效後,再次請求恢復正常。這就是“突刺現象”,也是這個限流框架的缺點。

第一次接口調用後,可以看到緩存中生成的key:

jd-zuul-dev-rate-limit:user-web:/user/getUser:/user/getUser
jd-zuul-dev-rate-limit:user-web:/user/getUser:/user/getUser-quota

自定義異常信息

這是網上的方式。實際上RateLimiterErrorHandler無法捕獲到限流異常信息429 TOO_MANY_REQUESTS,也就不能自定義異常返回信息。得通過ExceptionHandler返回自定義異常信息。

import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ExceptionHandler implements ErrorController {

    @Override
    public String getErrorPath() {

        return "error";
    }

    @RequestMapping(value="/error")
    public Rsp error(){
        return new Rsp(RSP_CODE_ERROR, "系統忙,請稍後再試");
    }

}

網關限流參數

自定義Key策略 

如果希望自己控制key的策略,可以通過自定義RateLimitKeyGenerator的實現來增加自己的策略邏輯。

例如:根據請求上的參數來對請求進行限流。比如有一個請求是http://localhost:8765/api-a//hello2?name=kevin,對相同的name值進行限流。我們設置了1分鐘內,限流10次,那麼如果1分鐘內,name是kevin的請求超過10次,就會發生限流。

RateLimitKeyGenerator的實現:

附記

這篇文章寫的很好,各種限流框架做了一個對比,列出各種優缺點,原理分析等等。

https://segmentfault.com/a/1190000020745218

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章