1. 程式人生 > 其它 >Spring Cloud Gateway 整合 Sentinel 閘道器限流(1)

Spring Cloud Gateway 整合 Sentinel 閘道器限流(1)

sentinel 從1.6.0 版本開始,提供了Spring Cloud Gateway Adapter 模組,支援兩種資源維度的限流。

  • Route 維度
  • 自定義API維度,可以利用提供的API來定義API分組,然後針對這些分組維度進行限流。需要引入如下的依賴。

        <dependency>
              <groupId>com.alibaba.csp</groupId>
              <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
              <version>1.7.1</version>
         </dependency>

  Route 維度限流

新增一個配置類 GatewayConfiguration

@Configuration

public class GatewayConfigurtion{
   private final List<ViewResolver> viewResolvers;

   private final ServerCodeConfigurer serverCodecConfigurer;

   public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolvers, ServerCodecConfigurer serverCodecConfigurer){
     this.viewResolvers=viewResolvers.getIfAvailable(Collections::emptyList)
     this.serverCodecConfigurer = serverCodecConfigurer;
   
   }

  // 注入 SentinelGatewayFilter
  @Bean
  @Order(Ordered.HIGHEST_PRECEDENCE)
  public GlobalFilter SentinelGatewayFilter(){
  
   }
   //注入限流異常處理器
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public  SentinelGatewayBlockExceptionHandler SentinelGatewayBlockExceptionHandler (){
   return new  SentinelGatewayBlockExceptionHandler (viewResolvers,serverCodecConfigurer);
   }


   @PostConstruct
   public void doInit(){
        initGatewayRules();
   }
    //初始化限流規則
   private void iniGatewayRules(){
     Set<GatewayFlowRule>  rules= new HashSet<>();
    GatewayFlowRule gatewayFlowRule=new GatewayFlowRule("nacos-gateway-provider").setCount(1).setIntervalSec(1);
    rules.add(gatewayFlowRule);
    GatewayRuleManager.loadRules(rules);


}
   





}

 配置類的主要功能如下:

  • 注入一個全侷限流過濾器SentinelGatewayFilter.
  • 注入限流異常處理器
  • 初始化限流規則。在當前版本中,sentinel-spring-cloud-gateway-adapter 還只能支援手動配置。

其中,GatewayFlowRule 閘道器限流規則中提供瞭如下屬性。

  • resource: 資源名稱,可以是閘道器中的route名稱或者使用者自定義的API分組名稱。
  • resourceMode: 資源模型,限流規則則是針對API Gateway的 route(RESOURCE_MODE_ROUTE_ID)還是使用者在Sentinel 中定義的API分組(RESOURCE_MODE_CUSTOM_API_NAME),預設route.
  • grade:限流指標維度,同限流規則的grade 欄位。
  • count:限流閾值。
  • intervalSec: 統計時間視窗,單位是秒, 預設是1 秒。 
  • controlBehavior: 流量整形的控制效果,同限流規則的controlBehavior欄位,目前支援快速失敗和勻速排隊兩種模式,預設快速失敗。
  • burst: 應對突發請求時額外允許的請求數目。
  • maxQueueingTimeoutMs:勻速排隊模式下的最長排隊時間,單位是毫秒,僅在勻速排隊模式下生效。
  • paramItem: 引數限流配置。若不提供,則代表針對引數進行限流,該閘道器規則將會被轉換成普通流控規則;否則會轉換熱點規則。其中的欄位如下。

parseStrategy: 從請求中提取引數的策略,目前支援提取來源IP(PARAM_PARSE_STRATEGY_CLIENT_IP)、Host(PARAM_PARSE_STRATEGY_HOST)、任意Header(PARAM_PARSE_STRATEGY_HEADER)和任意URL 引數(PARAM_PARSE_STRATEGY_URL_PARAM)四種模式。

fieldName:若提取策略選擇Header模式或者URL引數模式,則需要指定對應的Header名稱或URL引數名稱。

pattern和matchStrategy: 為後續引數匹配特性預留,目前末實現。

閘道器限流規則的載入可以通過GatewayRuleManager.loadRules(rules); 的方式手動載入,也可以通過GatewayRuleManager.register2Property(property)註冊動態限流規則(建議使用這種動態限流規則的方式)。

application.yml 檔案中的配置如下,由於SentinelGatewayFilter是全域性過濾器,閘道器配置不需要做任何調整。

spring:
  application:
    name: apring-cloud-nacos-gateway-consumer
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.216.128:8848
     gateway:
       discovery:
        locator:
          enabled: false#開啟從註冊中心動態建立路由的功能,利用微服務名進行路由
          lower-Case-Service-id: false
       routes:                  
        - id: nacos-gateway-provider
          uri: lb://spring-cloud-nacos-gateway-provider
          predicates:
            - Path=/nacos/**
          filters:
            # 驗證碼處理          
            - StripPrefix=1
       

 最後,通過測試工具訪問http://localhsot:8888/nacos/say, 當觸發限流之後,會獲得如下內容。

Blocked  by Sentinel:  ParamFlowException

  自定義API分組限流

自定義API分組限流實際上就是讓多個Route公用一個限流規則。舉例來說,假設有如下兩個URI匹配規則。

spring:
   cloud:
    gateway:
         routes:
           id:  foo_route
           uri: http://www.foo.com
           predicates:
             - Path=/foo/**
          - id: baz_route
          uri:http://www.baz.com
          predicates:
            -Path=/baz/**

 如果我們希望這兩個路由共用同一個限流規則,則可以採用自定義API分組限流的方式來實現。

private void initCustomizedApis(){
     Set<ApiDefinition> definitions= new HashSet<>();
     ApiDefinition apiDefinition=new ApiDefinition("first_customized_api")
     apiDefinition.setPredicateItem(new HashSet<ApiPredicateItem>(){{
       add(new ApiPathPredicateItem().setPattern("/foo/**"));
       add(new ApiPathPredicateItem().setPattern("/baz/**").setMatchStrategy
(SentinelGatewayContants.URL_MATCH_STRATEGY_PREFIX));

     }});
    definitions.add(apiDefinition);
    GatewayApiDefinitionManager.loadApiDefinitions(difinitions);


}

  上述程式碼主要是降/foo/** 和 /baz/**進行統一的分組,並提供一個name=first_sustomized_api, 然後再初始化閘道器限流規則時,針對該name設定限流規則。同時,我們可以通過setMatchStrategy 來設定不同path下的限流引數策略。

private void initGatewayRules(){
  GatewayFlowRule   customerFlowRule=new  GatewayFlowRule("first_customized_api").
setResourceMode(SentinelGatewayContants.RESOURCE_MODE_CUSTOM_API_NAME).setCount(5).setIntervalSec(1); }

  需要注意的是,再上述程式碼中,foo_route和 baz_route 這兩個路由ID 與 first_customized_api 都會標記為Sentinel 的資源(限流資源標記)。比如,當訪問閘道器的URI為http://localhsot:8888/foo/1時,Sentinel會統計foo_route、baz_route、first_customized_api 這些資源的流量情況。