Spring CloudGatewayおよびSpringCloud Alibaba SentinelGatewayの電流制限の実装

以前、Spring Cloud GatewayはRequestRateLimiterフィルターを実装しており、現在のゲートウェイへのすべてのリクエストに対して電流制限フィルターを実行します。電流が制限されている場合、デフォルトでHttp-429-Too ManyRequestsに応答します。 。RequestRateLimiterGatewayFilterFactoryは、デフォルトでRedisRateLimiterの現在の制限の実装を提供し、トークンバケットアルゴリズムを使用して現在の制限機能を実装します。次のように、Spring CloudGateway構成でフィルター—RequestRateLimiterを構成できます。

spring:
  cloud:
    gateway:
      routes:
        - id: redis_limiter
          uri: https://example.org
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20
server:
  port: 8081

redis-rate-Limiterには2つの属性があります。replenishRateはトークンバケット内のトークンが満たされる速度を意味し、1秒あたりに実行できるリクエストの数を意味します。burstCapacityはトークンバケットの容量を意味し、ユーザーが1秒あたりに実行するリクエストの最大数を意味します。 。redisの現在の制限はStripeに基づいており、次の依存関係を追加する必要があります。

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

KeyResolverインターフェイスを実装して、現在の制限要求のキーを設定し、現在の要求で現在を制限する要素を指定できます。次のコードは、現在を制限するためにチームから要求されたIPです。

public class IpAddressKeyResolver implements KeyResolver {
    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
    }
}

 KeyResolverのデフォルトの実装はPrincipalNameKeyResolverです。これは、ServerWebExchangeからプリンシパルを取得し、Principal.getNameメソッドを呼び出します。デフォルトでは、KeyResolverがキーを取得しない場合、要求は拒否されます。現在の制限フィルターのパラメーターを、それぞれdenyEmptyKeyとemptyKeyStatusに調整できます。以下は、IP電流制限の構成です。

spring:
  cloud:
    gateway:
      routes:
        - id: redis_limiter
          uri: https://example.org
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20
                denyEmptyKey: true
                emptyKeyStatus: SERVICE_UNAVAILABLE
                keyResolver: '#{@ipAddressKeyResolver}'
server:
  port: 8081

 インターフェイスを呼び出すと、redisはそれぞれrequest_rater_limiter。{ip} .timestampとrequest_rater_limiter。{ip} .tokensの2つのキーを生成します。Spring Cloud Gatewayは、Redisに基づくRateLimiter電流制限モードのみを実装します。AbstractRateLimiterを実装してxianliuqをカスタマイズし、構成によって現在のリミッターを指定できます。

rateLimiter:  #{@rateLimiterName}

Spring Cloud Alibaba Sentinelは、バージョン1.6からSpring Cloud Gatewayをサポートします。これは、ルートディメンションとカスタムAPIディメンションの2つのリソースディメンションの現在の制限をサポートします。提供されたAPIを使用してAPIグループをカスタマイズし、これらのグループを制限できます。フロー。Sentinel-Adapter依存関係パッケージを導入する必要があります。

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

以前にSentinelを導入したときは、FlowRuleを使用してフロー制限ルールを提供していましたが、Spring Cloud Gatewayでは、SentinelはGatewayFlowRuleをフロー制限ルールとして使用していました。以下は簡単な例です。

private void initGatewayRules() {
    Set<GatewayFlowRule> gatewayFlowRules = new HashSet<GatewayFlowRule>();
    GatewayFlowRule rule = new GatewayFlowRule().setCount(5).setIntervalSec(1).setResource("gateway-sentinel-limiter");
    gatewayFlowRules.add(rule);
    GatewayRuleManager.loadRules(gatewayFlowRules);
}

FlowRuleと同様に、GatewayFlowRuleは次のプロパティを提供します。ここでは、ソースコードでプロパティを設定するために、コードの一部を直接コピーしてコメントします。コードは次のとおりです。

//设置资源名称,可以是网关配置中的route名称或者用户自定义的API分组
public GatewayFlowRule setResource(java.lang.String resource) {  }
//资源模型,限流针对API Gateway的route还是用户在sentinel定义的API分组
public GatewayFlowRule setResourceMode(int resourceMode) {  }
// 限流指标维度,同FlowRule的grade字段
public GatewayFlowRule setGrade(int grade) { }
//同FlowRule的controlBehavior字段,支持快速失败和匀速排队
public GatewayFlowRule setControlBehavior(int controlBehavior) { }
//限流阈值
public GatewayFlowRule setCount(double count) {  }
//统计时间窗口,单位为秒,默认是1秒
public GatewayFlowRule setIntervalSec(long intervalSec) { }
//应对突发请求时额外允许的请求数目
public GatewayFlowRule setBurst(int burst) { }
//匀速排队下最长排队时间
public GatewayFlowRule setMaxQueueingTimeoutMs(int maxQueueingTimeoutMs) { }
//参数限流配置,若不提供,则代表不针对参数进行限流。从请求中提取参数的策略,下面的类为GatewayParamFlowItem提供的属性
public GatewayFlowRule setParamItem(GatewayParamFlowItem paramItem) { }
public class GatewayParamFlowItem {
    private java.lang.Integer index;
    //解析策略:目前支持IP,HOST,任意Header和任意URL参数四种模式,
    private int parseStrategy;
    //为Header和URL策略时的Header 名称或者URL参数名称
    private java.lang.String fieldName;
    //下面的两个目前没有实现,后续可能会实现
    private java.lang.String pattern;
    private int matchStrategy;
}

SentinelによるSpringCloud Gatewayの電流制限のサポートは、実際にはグローバルフィルターです。グローバルフィルターをコンテナーに挿入すると、グローバルフィルターが有効になります。SentinelがSpring CloudGatewayで使用する構成は次のとおりです。

Configuration
public class SentinelRateLimiterConfiguation {
    private final List<ViewResolver> viewResolverList;
    private final ServerCodecConfigurer serverCodecConfigurer;
    //注入视图解析器
    public SentinelRateLimiterConfiguation(ObjectProvider<List<ViewResolver>> viewResolverList, ServerCodecConfigurer serverCodecConfigurer) {
        this.viewResolverList = viewResolverList.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }
    //注入Sentinel全局过滤器SentinelGatewayFilter
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }
    //注入限流异常处理器
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        return new SentinelGatewayBlockExceptionHandler(viewResolverList, serverCodecConfigurer);
    }
    //初始化限流规则
    @PostConstruct
    public void initRules() {
        initGatewayRules();
    }

    private void initGatewayRules() {
        Set<GatewayFlowRule> gatewayFlowRules = new HashSet<GatewayFlowRule>();
        GatewayFlowRule rule = new GatewayFlowRule().setCount(5).setIntervalSec(1).setResource("gateway-sentinel-limiter");
        gatewayFlowRules.add(rule);
        GatewayRuleManager.loadRules(gatewayFlowRules);
    }
}

Sentinelを構成した後、Spring CloudGatewayゲートウェイの関連する構成を構成する必要があります。構成は次のとおりです。

spring:
  cloud:
    gateway:
      routes:
        - id: gateway-sentinel-limiter
          uri: https://example.org
          predicates:
            -path=/sentinel/rate

前に述べたように、ルート電流制限を使用することに加えて、電流制限のグループ化をカスタマイズすることもできます。実際、複数のルートが1つの電流制限ルールを使用するようにします。参加するには、現在の制限ルールを使用するために次の2つのルートが必要です。

spring:
  cloud:
    gateway:
      routes:
        - id: exmaple-sentinel-limiter
          uri: https://example.org
          predicates:
            -path=/sentinel/rate
        - id: example1-sentinel-limiter
            uri: https://example1.org
            predicates:
              -path=/sentinel1/rate

次に、上記の2つのルートを同じグループに構成してから、同じ電流制限ルールを使用できます。次のコードは、上記の2つのルートを1つのグループに定義します。

private void initCustomizedApis() {
    ApiDefinition api = new ApiDefinition("customized-apis");
    Set<ApiPredicateItem> apiPredicateItems = new HashSet<ApiPredicateItem>();
    apiPredicateItems.add(new ApiPathPredicateItem().setPattern("/sentinel/rate"));
    apiPredicateItems.add(new ApiPathPredicateItem().setPattern("/sentinel1/rate").setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_REGEX));
    api.setPredicateItems(apiPredicateItems);
}

グループ化を定義した後、現在の制限ルールを定義するときにリソースを設定するとき、つまりsetResource()のときに、リソースをcustomized-apisに設定できます。コードは次のように表示されます。

private void initGatewayRules() {
        Set<GatewayFlowRule> gatewayFlowRules = new HashSet<GatewayFlowRule>();
        GatewayFlowRule rule = new GatewayFlowRule().setCount(5).setIntervalSec(1).setResource("customized-apis").setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME);
        gatewayFlowRules.add(rule);
        GatewayRuleManager.loadRules(gatewayFlowRules);
    }

 

おすすめ

転載: blog.csdn.net/wk19920726/article/details/108568218