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 这些资源的流量情况。

 

posted @ 2021-07-16 11:11  天竹冰程  阅读(1531)  评论(0编辑  收藏  举报