成功:SpringCloud Gateway限流_RateLimiter_RedisRateLimiter

文件名稱 版本號 作者 qq 版本
成功:SpringCloud Gateway限流_RateLimiter_RedisRateLimiter v0.0.1 學生宮布 8416837 SpringBoot 2.2.6
SpringCloud Gateway 2.2.2

配置

yaml

  • 注意看註釋
  • 反面教材 [錯誤的配置],id不對,應該配置在id是微服務的配置大項下面。這樣不會起效,按下文修正後,起效了。
spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route # 過濾器名稱,不必在意
        uri: https://example.org # 上游,有的地方叫下游-_-||
        predicates:
        	- Path=/xxx/**
        filters:
			- StripPrefix=1
	        - name: RequestRateLimiter # 官方給的名稱,對應Java類,有需要再改
	          args:
	            redis-rate-limiter.replenishRate: 10 # 每秒補充10個
	            redis-rate-limiter.burstCapacity: 20 # 突發20個
	            redis-rate-limiter.requestedTokens: 1 # 每次請求消耗1個
	            # rate-limiter: "#{@redisRateLimiter}" # 限流器
	            key-resolver: "#{@userAPIKeyResolver}" # 限流key|字段解析器
  • 正確的
		...
		# 系統模塊
        - id: abc-system
          uri: lb://abc-system
          predicates:
            - Path=/system/**
          filters:
            - StripPrefix=1
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 1
                redis-rate-limiter.burstCapacity: 2
                key-resolver: "#{@userAPIKeyResolver}"
                # key-resolver: "#{@ipKeyResolver}"

依賴

  • xml
<dependency>
 	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
	<!-- 版本號可以繼承父項目或自己寫 RELEASE表示最新版-->
	<version>RELEASE</version>
</dependency>

Java

標識
  • user結合API 限流成功

前提是QueryParams攜帶user參數(一般不會這麼做),否則報空指針錯誤

// 根據什麼字段限流,甚至是組合字段
@Bean
public KeyResolver userAPIKeyResolver() {
	// rt,根據字段限流,下文根據Query參數值作爲限流標識,請酌情更改爲自己的方式
    return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
    // todo 獲取消費者消費的API的id,與user組合
}
  • ip 限流成功 響應碼429 服務降級 拒絕服務
/**
     * 功能描述: 基於ip限流
     *
     * @param: []
     * @return: org.springframework.cloud.gateway.filter.ratelimit.KeyResolver
     * @qq: 8416837
     * @author: cc
     * @date: 2020/6/10 11:56
     */
    @Bean("ipKeyResolver")
    public KeyResolver ipKeyResolver() {

        System.out.println("限流解析器");

        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
    }
  • 限流器 Redis限流器(可以省去,可以使用上文的yaml配置代替)
	@Bean
	RedisRateLimiter redisRateLimiter() {
		return new RedisRateLimiter(9, 16); // yaml配置文件已經有了,那麼這裏就省了。9,16對應replenishRate、burstCapacity
	}
  • 其它key限流

原理一樣,使用設置的key存儲redis令牌,調用的時候消耗令牌,單位時間內的令牌耗盡則拒絕服務,另外還有個突發流量功能,當突發的時候,令牌會增加,見配置burstCapacity

執行

將配置拷貝到項目或配置中心、代碼拷貝到項目,並修改Java代碼:KeyResolver
啓動項目,使用壓測工具壓測或者手動發送Http請求,進行測試。

故障

不起效

  • 多線程調用接口,每秒發送10個請求,仍然成功了:
    在這裏插入圖片描述
分析原因
  • 限流過濾器沒有攔截到請求
  • 可能與路由配置有關,回顧路由配置:
		...
		# 限流
        - id: requestratelimiter_route # 過濾器名稱,不必在意
          uri: lb://abc-system # 上游,有的地方叫下游-_-||
          predicates:
            - Path=/system/**
          filters:
          - name: RequestRateLimiter # 官方給的名稱,對應Java類,有需要再改
            args:
            ...
  • requestratelimiter_route名稱是按照官方的,應該沒問題;
  • uri表示路由的目標是它,也沒問題吧;
  • predicates斷言是Path類型,是個正則,當正則匹配訪問路徑時,即將請求指向目標,好像也沒問題;
  • RequestRateLimiter ,沒有找到這個類,但是好像找到了相關Bean:
解決方案

1)增加public,KeyResolver userAPIKeyResolver() {改爲public KeyResolver userAPIKeyResolver() {
2)限流配置改正確

		# 系統模塊
        - id: abc-system
          uri: lb://abc-system
          predicates:
            - Path=/system/**
          filters:
            - StripPrefix=1
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 1
                redis-rate-limiter.burstCapacity: 2
                key-resolver: "#{@userAPIKeyResolver}"

限流成功

根據配置進行限流:
在這裏插入圖片描述
調用接口,限流開始工作,日誌
在這裏插入圖片描述
上圖使用多線程模擬10個併發,只有2個請求成功,剩餘請求返回429(Too Many Request),說明限流已經ok了,更多細節可以繼續優化。

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