欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring Cloud Gateway層限流實現過程

 更新時間:2024年08月13日 09:48:25   作者:it_lihongmin  
這篇文章主要介紹了Spring Cloud Gateway層限流實現過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

寫在前面的話

  • 高并發(fā)的三駕馬車:緩存、降級、限流,這里僅僅說限流
  • 常用的限流算法有:計數器算法、固定窗口算法、滑動窗口算法、漏桶算法、令牌桶算法;每種算法的特點和優(yōu)缺點這里不展開,比較適用的限流算法基本都會選擇令牌桶,并且這里基于Spring Cloud Gateway Redis本身默認就是基于令牌桶算法實現
  • 限流按照類型分為:單機、分布式;
  • 限流按照請求流量的路徑分為:nginx、gateway、微服務
  • 如果僅僅使用于單機環(huán)境:谷歌guava的RateLimiter、(AtomicInteger、Semaphore)【AQS】都是可以選擇的; 但是在說到高并發(fā)基本已經是分布式環(huán)境,此時的常用方案可以基于nginx的ngx_http_limit_req_module模塊、 gateway層基于 redis(底層使用lua腳本)、阿里的sentinel(需要單獨搭建服務)等方案
  • 該方案選擇使用spring cloud gateway RequestRateLimiter進行限流,可選擇的策略有:基于訪問的ip進行控制,基于訪問的請求參數進行控制(前提是接口需要有對應的訪問參數),基于actuator實時監(jiān)控進行控制(比如服務器的cpu達到80%),基于hystrix配置的策略進行控制等

當前選擇的方案在是 Spring Cloud Gateway層使用 redis作為分布式的協作中心,默認底層使用令牌桶方式實現,一定要清楚,當前在這個位置:

如果再細分一下,當前位于gateway的內部的這個位置:

實現(這個省略了gateway的搭建和配置等):

1、在gateway網關服務進入redis的pom

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
    <version>2.3.2.RELEASE</version>
</dependency>

2、yml配置

spring:
  application:
    name: kevin-gateway
  redis:
    host: 82.156.54.7
    port: 6379
    password: 123456
  cloud:
    nacos:
      discovery:
        server-addr: 82.156.54.7:8848
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowCredentials: true
            allowedOrigins: "*"
            allowedMethods: "*"
            allowedHeaders: "*"
        add-to-simple-url-handler-mapping: true
      # 默認過濾器(對所有route均生效)
      default-filters:
        # 請求限速配置
        - name: RequestRateLimiter
          args:
            # 如果keyResolver返回空key,則拒絕該請求403,默認true表示拒絕,false則表示允許訪問
            deny-empty-key: false
            # 令牌桶算法每秒補充的token數量(每秒的請求數量)spring-boot-starter-data-redis-reactive
            redis-rate-limiter.replenishRate: 10
            # 令牌桶算法token最大數量(每秒的最大請求數量)
            redis-rate-limiter.burstCapacity: 15
            # 單次請求消費的token數量
            redis-rate-limiter.requestedTokens: 10
            # 自定義的KeyResolver(從請求exchange解析id,用于區(qū)分限流的獨立單元,如用戶ID、remoteAddr、sessionId等)
            key-resolver: "#{@ipKeyResolver}"
      routes:
        - id: mosty-base
          uri: lb://mosty-base
          predicates:
            - Path=/mosty-base/**
          filters:
            - StripPrefix=1
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20
                redis-rate-limiter.requestedTokens: 10
                key-resolver: "#{@ipKeyResolver}"
        - id: mosty-search
          uri: lb://MOSTY-SEARCH
          predicates:
            - Path=/mosty-search/**
          filters:
            - StripPrefix=2

如上,首先需要進入redis的配置

其次配置限流的Filter配置信息,允許配置全局過濾器對所有的route生效,也可以根據需求對每個route進行單獨配置

配置參數說明:

  • name必須寫 RequestRateLimiter

args參數:

  • redis-rate-limiter.replenishRate:發(fā)送令牌的速率
  • redis-rate-limiter.burstCapacity: 令牌桶的容量
  • reids-rate-limiter.requestedTokens: 每個請求耗費的令牌數
  • key-resolver:如上所示是配置的一個spring bean的名稱,如果沒有配置則會獲取到KeyResolver的默認實現PrincipalNameKeyResolver,并且訪問接口都會返回 http 403狀態(tài)碼(與下面的deny-empty-key值相關)
  • deny-empty-key: false 如果keyResolver返回空key,則拒絕該請求403,默認true表示拒絕,false則表示允許訪問

1、ip限流策略

yml中配置 keyResolver:"#{@ipKeyResolver}"

@Bean(name = "ipKeyResolver")
public KeyResolver ipKeyResolver() {
   return new KeyResolver() {
      @Override
      public Mono<String> resolve(ServerWebExchange exchange) {
         String hostName = Objects.requireNonNull(exchange.getRequest()
                               .getRemoteAddress()).getHostName();
         System.out.println("hostName:" + hostName);
         return Mono.just(hostName);
      }
   };
}

基于限流策略,正常訪問的效果,以及被限流的效果(返回標準的Http 429編碼,Too Many Request)

2、請求參數限流策略

yml中配置 keyResolver:"#{@userKeyResolver}"

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

在下面的微服務的接口中一定要有該參數,即需要能在請求參數中獲取到該值

@GetMapping("/getUserNameByUserId")
public String userInfo(@RequestParam("userId") String userId) {
   // 查詢數據庫獲取
   return "user name of" + userId;
}

3、請求路徑(即接口)限流

yml中配置 keyResolver:"#{@requestPathKeyResolver}"

@Bean("requestPathKeyResolver")
public KeyResolver requestPathKeyResolver() {
   return exchange -> Mono.just(Objects.requireNonNull(
                        exchange.getRequest().getURI().()));
}

4、基于hystrix熔斷進行限流策略

基于上面的引入pom:spring-boot-starter-data-redis-reactive外,還需要引入

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

將Hystrix配置為全局的過濾器(對所有的 route生效),如下

說明:

name執(zhí)行過濾器的類型,指向了 Hystrix過濾器

args:default-filters的Hystrix將會使用HystrixCommand打包剩余的過濾器,并命名為fallbackcmd,我們還配置了可選的參數fallbackUri,降級邏輯被調用,請求將會被轉發(fā)到URI為/fallbackcontroller的控制器處理

spring:
  cloud:
    gateway:
      # 默認過濾器(對所有route均生效)
      default-filters:
        - name: Hystrix
          args:
            name: fallbackcmd
            fallbackUri: forward:/fallbackcontroller

添加 Hystrix的fallback的控制器接口方法

此時需要添加一個fallback的接口,并且返回想要的數據結構

@ResponseBody
@RequestMapping(value = "/fallbackcontroller")
public ResponseResult<Object> fallBackController() {
   return ResponseResult.fail(HttpStatus.TOO_MANY_REQUESTS.value(), "超時限流",  null);
}

生效還需要配置hystrix的超時時間(yml配置如下):

hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds

并且記得在啟動類上添加Hystrix的啟動項

  • @EnableHystrix

為了實現效果此時將待訪問的接口直接進行sleep 5s,測試效果

@Slf4j
@RestController
public class TestController {
 
    @RequestMapping("/test/fallback")
    public Object fallacak() throws InterruptedException {
        Thread.sleep(5000);
        log.info("熔斷處理?。。?);
        return "Service Error?。?!";
    }
}

總結

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

最新評論