spring cloud網關通過Zuul RateLimit 限流配置


在平常項目中為了防止一些沒有token訪問的API被大量無限的調用,需要對一些服務進行API限流。就好比拿一些注冊或者發驗證碼的一些接口,如果被惡意無限的調用,多少會造成一些費用的產生,發短信或者郵件都是一些第三方接口,次數越多,當然費用也就越多了,嚴重的直接導致服務崩潰。spring cloud api-gateway中引入限流的配置還是必須的。

引入依賴

在pom文件中引入Zuul RateLimit的依賴


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

配置信息


更詳細的配置解讀下面有寫,這里只是簡單配置一下,以下這個配置就可以對服務進行限流了
zuul:
  routes: 你的路由配置
    test:
      path: 
      serviceId: 
  ratelimit:
    enabled: true
    policies:
      test: 路由名
        limit: 限制次數
        refresh-interval: 刷新時間
        type: 類型

RateLimit源碼簡單分析

本地讓自己的一個服務配置為一分鍾內該服務的API只能訪問十次,超過十次,網關就會報錯

zuul:
  routes:
    test:
      path: /api/test/**
      serviceId: hscf-cloud-test-9457
  ratelimit:
    enabled: true
    policies:
      test:
        limit: 10
        refresh-interval: 60
        type: origin  限流方式

下面通過源碼簡要分析一下

RateLimit類是繼承ZuulFilter,內中的變量不難看出就是我們在yml文件中配置的屬性值。RateLimit內中的部分源碼,filterType為“pre”表示在每一個API訪問之前進行攔截,LIMIT_HEADER,REMAINING_HEADER,RESET_HEADER這三個變量應該就是獲取我們配置的訪問次數,還有記錄該時間內剩余的訪問次數。

public class RateLimitFilter extends ZuulFilter {
    public static final String LIMIT_HEADER = "X-RateLimit-Limit";
    public static final String REMAINING_HEADER = "X-RateLimit-Remaining";
    public static final String RESET_HEADER = "X-RateLimit-Reset";

    public String filterType() {
        return "pre";
    }
    public int filterOrder() {
        return -1;
    }
    public boolean shouldFilter() {
        return this.properties.isEnabled() && this.policy(this.route()).isPresent();
    }

主體邏輯run()中進行判斷。先通過this.policy(route).ifPresent((policy)判斷policy配置信息是否存在,存在的話會讀
取到當前的限制值,還剩余的限制值,最終判斷剩余的限制值是否小於0,小於0的話就會報出太多請求的異常
TOO_MANY_REQUESTS(429, "Too Many Requests")

    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletResponse response = ctx.getResponse();
        HttpServletRequest request = ctx.getRequest();
        Route route = this.route();
        this.policy(route).ifPresent((policy) -> {
            String key = this.rateLimitKeyGenerator.key(request, route, policy);
            Rate rate = this.rateLimiter.consume(policy, key);
            response.setHeader("X-RateLimit-Limit", policy.getLimit().toString());
            response.setHeader("X-RateLimit-Remaining", String.valueOf(Math.max(rate.getRemaining().longValue(), 0L)));
            response.setHeader("X-RateLimit-Reset", rate.getReset().toString());
            if(rate.getRemaining().longValue() < 0L) {
                ctx.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());
                ctx.put("rateLimitExceeded", "true");
                throw new ZuulRuntimeException(new ZuulException(HttpStatus.TOO_MANY_REQUESTS.toString(), HttpStatus.TOO_MANY_REQUESTS.value(), (String)null));
            }
        });
        return null;
    }
。。。。。。

控制台的異常信息,異常code為429,也就是太多請求的異常:TOO_MANY_REQUESTS(429, "Too Many Requests")

RateLimit詳細的配置信息解讀

zuul:

    ratelimit:

        key-prefix: your-prefix  #對應用來標識請求的key的前綴

        enabled: true

        repository: REDIS  #對應存儲類型(用來存儲統計信息)

        behind-proxy: true  #代理之后

        default-policy: #可選 - 針對所有的路由配置的策略,除非特別配置了policies

             limit: 10 #可選 - 每個刷新時間窗口對應的請求數量限制

             quota: 1000 #可選-  每個刷新時間窗口對應的請求時間限制(秒)

              refresh-interval: 60 # 刷新時間窗口的時間,默認值 (秒)

               type: #可選 限流方式

                    - user

                    - origin

                    - url

          policies:

                myServiceId: #特定的路由

                      limit: 10 #可選- 每個刷新時間窗口對應的請求數量限制

                      quota: 1000 #可選-  每個刷新時間窗口對應的請求時間限制(秒)

                      refresh-interval: 60 # 刷新時間窗口的時間,默認值 (秒)

                      type: #可選 限流方式

                          - user

                          - origin

                          - url

  • url類型的限流就是通過請求路徑區分
  • origin是通過客戶端IP地址區分
  • user是通過登錄用戶名進行區分,也包括匿名用戶

目前只是將網關中的限流方式使用連起來,源碼中的原理知道了一下,后續可以繼續進行擴展,可以針對請求上的參數進行請求攔截限流


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM