天天看點

spring cloud gateway 網關_spring-cloud-gateway限流

spring cloud gateway 網關_spring-cloud-gateway限流

概述

限流

:網關上有大量請求,對指定服務進行限流,可以很大程度上提高服務的可用性與穩定性,限流的目的是通過對并發通路/請求進行限速,或對一個時間視窗内的請求進行限速來保護系統。一旦達到限制速率則可以拒絕服務、排隊或等待、降級。

在 Spring Cloud Gateway 中,有

Filter過濾器

,是以可以在

pre

類型的 Filter 中自行實作上述三種過濾器。但是限流作為網關最基本的功能,Spring Cloud Gateway 官方就提供了

RequestRateLimiterGatewayFilterFactory

這個類,适用在 Redis 内的通過執行 Lua 腳本實作了令牌桶的方式。具體實作邏輯在

RequestRateLimiterGatewayFilterFactory

類中,lua 腳本在如下圖所示的檔案夾中:

spring cloud gateway 網關_spring-cloud-gateway限流

限流配置

應一小夥伴要求, 将 demo 更新到了最新版本

  • spring-cloud-dependencies: Hoxton.SR3
  • spring-boot-dependencies: 2.2.6.RELEASE

代碼放置在

github

.

  1. 修改配置檔案
server:
  port: 2000
spring:
  application:
    name: idc-gateway2
  redis:
    host: localhost
    port: 6379
    timeout: 6000ms  # 連接配接逾時時長(毫秒)
    jedis:
      pool:
        max-active: 1000  # 連接配接池最大連接配接數(使用負值表示沒有限制)
        max-wait: -1ms      # 連接配接池最大阻塞等待時間(使用負值表示沒有限制)
        max-idle: 10      # 連接配接池中的最大空閑連接配接
        min-idle: 5       # 連接配接池中的最小空閑連接配接
  cloud:
    consul:
      host: localhost
      port: 8500
    gateway:
      discovery:
        locator:
          enabled: true # gateway可以通過開啟以下配置來打開根據服務的serviceId來比對路由,預設是大寫
      routes:
        - id: provider1
          uri: lb://idc-provider1
          predicates:
            - Path=/p1/**
          filters:
            - StripPrefix=1
            - name: RequestRateLimiter
              args:
                key-resolver: '#{@ipKeyResolver}'
                redis-rate-limiter.replenishRate: 1
                redis-rate-limiter.burstCapacity: 3
        - id: provider2
          uri: lb://idc-provider2
          predicates:
            - Path=/p2/**
          filters:
            - StripPrefix=1
           

在上面的配置檔案,指定程式的端口為 2000,配置了 redis 的資訊,并配置了 RequestRateLimiter 的限流過濾器,該過濾器需要配置三個參數:

  • burstCapacity,令牌桶總容量。
  • replenishRate,令牌桶每秒填充平均速率。
  • key-resolver,用于限流的鍵的解析器的 Bean 對象的名字。它使用 SpEL 表達式根據#{@beanName}從 Spring 容器中擷取 Bean 對象。
  1. 限流配置

這裡根據使用者 ID 限流,請求路徑中必須攜帶 userId 參數

@Bean
KeyResolver userKeyResolver() {
  return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}
           

KeyResolver 需要實作 resolve 方法,比如根據 userid 進行限流,則需要用 userid 去判斷。實作完 KeyResolver 之後,需要将這個類的 Bean 注冊到 Ioc 容器中。

如果需要根據 IP 限流,定義的擷取限流 Key 的 bean 為:

@Primary
@Bean
KeyResolver ipKeyResolver() {
  return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
           

通過 exchange 對象可以擷取到請求資訊,這邊用了 HostName,如果你想根據使用者來做限流的話這邊可以擷取目前請求的使用者 ID 或者使用者名就可以了,比如:

如果需要根據接口的 URI 進行限流,則需要擷取請求位址的 uri 作為限流 key,定義的 Bean 對象為:

@Bean
KeyResolver apiKeyResolver() {
  return exchange -> Mono.just(exchange.getRequest().getPath().value());
}
           
  1. 完整的配置檔案:
@Component
public class RateLimitConfig {
    @Bean
    KeyResolver userKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
    }

    @Primary
    @Bean
    KeyResolver ipKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
    }

    @Bean
    KeyResolver apiKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getPath().value());
    }
}
           

限流演練

這裡我們用

postman

進行測試

spring cloud gateway 網關_spring-cloud-gateway限流
spring cloud gateway 網關_spring-cloud-gateway限流
spring cloud gateway 網關_spring-cloud-gateway限流
spring cloud gateway 網關_spring-cloud-gateway限流

基于系統負載的動态限流

在實際工作中,我們可能還需要根據網絡連接配接數、網絡流量、CPU 或記憶體負載等來進行動态限流。在這裡我們以 CPU 為栗子。

我們需要借助 Spring Boot Actuator 提供的 Metrics 能力進行實作基于 CPU 的限流 —— 當 CPU 使用率高于某個門檻值就開啟限流,否則不開啟限流。

我們在項目中引入 Actuator 的依賴坐标

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
           

然後基于過濾器和 metrics 名額判斷是否需要限流。

最後

本文到此結束,感謝大家的閱讀。歡迎關注公衆号【當我遇上你】