资讯专栏INFORMATION COLUMN

Spring Cloud Gateway 扩展支持动态限流

beanlam / 3696人阅读

摘要:以流量为切入点,从流量控制熔断降级系统负载保护等多个维度保护服务的稳定性分布式系统的流量防卫兵。欢迎关注我们获得更多的好玩实践

之前分享过 一篇 《Spring Cloud Gateway 原生的接口限流该怎么玩》, 核心是依赖Spring Cloud Gateway 默认提供的限流过滤器来实现

原生RequestRateLimiter 的不足

配置方式

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: lb://pigx-upms
        order: 10000
        predicates:
        - Path=/admin/**
        filters:
        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 1  
            redis-rate-limiter.burstCapacity: 3
            key-resolver: "#{@remoteAddrKeyResolver}" #SPEL表达式去的对应的bean
        - StripPrefix=1

RequestRateLimiterGatewayFilterFactory

public GatewayFilter apply(Config config) {
    KeyResolver resolver = getOrDefault(config.keyResolver, defaultKeyResolver);
    RateLimiter limiter = getOrDefault(config.rateLimiter,
            defaultRateLimiter);
    boolean denyEmpty = getOrDefault(config.denyEmptyKey, this.denyEmptyKey);
    HttpStatusHolder emptyKeyStatus = HttpStatusHolder
            .parse(getOrDefault(config.emptyKeyStatus, this.emptyKeyStatusCode));

    return (exchange, chain) -> {
                return exchange.getResponse().setComplete();
            });
        });
    };
}

在实际生产过程中,必定不能满足我们的需求

生产中路由信息是保存数据库持久化或者配置中心,RequestRateLimiterGatewayFilterFactory 并不能随着持久化数据的改变而动态改变限流参数,不能做到实时根据流量来改变流量阈值

Sentinel Spring Cloud Gateway 流控支持 Sentinel 是什么?

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性,分布式系统的流量防卫兵。
从 1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:
route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 routeId
自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组

pom 依赖


    com.alibaba.cloud
    spring-cloud-alibaba-sentinel-gateway




    com.alibaba.csp
    sentinel-datasource-nacos
配置本地路由规则及其sentinel数据源
spring:
  application:
    name: sentinel-spring-cloud-gateway
  cloud:
    gateway:
      enabled: true
      discovery:
        locator:
          lower-case-service-id: true
      routes:
      - id: pigx_route
        uri: https://api.readhub.cn
        predicates:
        - Path=/topic/**
    sentinel:
      datasource.ds1.nacos:
        server-addr: 127.0.0.1:8848
        data-id: gw-flow
        group-id: DEFAULT_GROUP
        ruleType: gw-api-group
      filter:
        enabled: true
配置nacos数据源中的限流策略

常用限流策略 常量

以客户端IP作为限流因子
public static final int PARAM_PARSE_STRATEGY_CLIENT_IP = 0;
以客户端HOST作为限流因子
public static final int PARAM_PARSE_STRATEGY_HOST = 1;
以客户端HEADER参数作为限流因子
public static final int PARAM_PARSE_STRATEGY_HEADER = 2;
以客户端请求参数作为限流因子
public static final int PARAM_PARSE_STRATEGY_URL_PARAM = 3;
以客户端请求Cookie作为限流因子
public static final int PARAM_PARSE_STRATEGY_COOKIE = 4;

核心源码解析 SentinelGatewayFilter

sentinel通过扩展Gateway的过滤器,通过选择的不同GatewayParamParser 过处理请求限流因子和数据源中的配置进行比较

源码如下:

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);

    Mono asyncResult = chain.filter(exchange);
    if (route != null) {
        String routeId = route.getId();
        Object[] params = paramParser.parseParameterFor(routeId, exchange,
            r -> r.getResourceMode() == SentinelGatewayConstants.RESOURCE_MODE_ROUTE_ID);
        String origin = Optional.ofNullable(GatewayCallbackManager.getRequestOriginParser())
            .map(f -> f.apply(exchange))
            .orElse("");
        asyncResult = asyncResult.transform(
            new SentinelReactorTransformer<>(new EntryConfig(routeId, EntryType.IN,
                1, params, new ContextConfig(contextName(routeId), origin)))
        );
    }

    Set matchingApis = pickMatchingApiDefinitions(exchange);
    for (String apiName : matchingApis) {
        Object[] params = paramParser.parseParameterFor(apiName, exchange,
            r -> r.getResourceMode() == SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME);
        asyncResult = asyncResult.transform(
            new SentinelReactorTransformer<>(new EntryConfig(apiName, EntryType.IN, 1, params))
        );
    }

    return asyncResult;
}
效果演示

以上nacos 配置为 每秒只能通过5个请求,我们使用jmeter 4.0 来并发10个线程测试一下



通过上图可以结果证明sentinel限流确实有效

动态修改限流参数

sentinel-datasource-nacos 作为sentinel的数据源,可以从如上 nacos 管理台实时刷新限流参数及其阈值

目前sentinel dashboard 1.6.2 暂未实现gateway 流控图形化控制 , 1.7.0 会增加此功能

总结

以上源码参考个人项目 基于Spring Cloud、OAuth2.0开发基于Vue前后分离的开发平台

QQ: 2270033969 一起来聊聊你们是咋用 spring cloud 的吧。

欢迎关注我们获得更多的好玩JavaEE 实践

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106177.html

相关文章

  • Spring Cloud Gateway 扩展支持动态限流

    摘要:以流量为切入点,从流量控制熔断降级系统负载保护等多个维度保护服务的稳定性分布式系统的流量防卫兵。欢迎关注我们获得更多的好玩实践 之前分享过 一篇 《Spring Cloud Gateway 原生的接口限流该怎么玩》, 核心是依赖Spring Cloud Gateway 默认提供的限流过滤器来实现 原生RequestRateLimiter 的不足 配置方式 spring: clou...

    妤锋シ 评论0 收藏0
  • 阿里Sentinel支持Spring Cloud Gateway

    摘要:应对突发请求时额外允许的请求数目。匀速排队模式下的最长排队时间,单位是毫秒,仅在匀速排队模式下生效。和为后续参数匹配特性预留,目前未实现。 1. 前言 4月25号,Sentinel 1.6.0 正式发布,带来 Spring Cloud Gateway 支持、控制台登录功能、改进的热点限流和注解 fallback 等多项新特性,该出手时就出手,紧跟时代潮流,昨天刚发布,今天我就要给大家分...

    chengtao1633 评论0 收藏0
  • spring cloud gateway限流

    摘要:常见的限流方式,比如适用线程池隔离,超过线程池的负载,走熔断的逻辑。在令牌桶算法中,存在一个桶,用来存放固定数量的令牌。,令牌桶每秒填充平均速率。 转载请标明出处: https://www.fangzhipeng.com本文出自方志朋的博客 在高并发的系统中,往往需要在系统中做限流,一方面是为了防止大量的请求使服务器过载,导致服务不可用,另一方面是为了防止网络攻击。 常见的限流方式,...

    joy968 评论0 收藏0
  • Spring Cloud Gateway限流实战

    摘要:欢迎访问我的欢迎访问我的内容所有原创文章分类汇总及配套源码,涉及等本篇概览本篇概览本文是实战系列的第八篇,经过前面的学习,咱们对过滤器已了解得差不多,今天来补全过滤器的最后一个版块限流默认的限流器是基于实现的,限流算法是大家熟悉的令牌桶关于欢迎访问我的GitHubhttps://github.com/zq2599/blog_demos内容:所有原创文章分类汇总及配套源码,涉及Java、Doc...

    stonezhu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<