irpas技术客

微服务系列:服务网关 Spring Cloud Gateway 限流配置_zhang33565417_gateway限流配置

网络 7935

上一篇文章 微服务系列:服务网关 Spring Cloud Gateway 入门 中我们学习了 Spring Cloud Gateway 的一些入门知识,今天我们来学习怎么使用 Spring Cloud Gateway 来实现限流。

话不多说,开始今天的学习。

限流配置 1. 相关概念

限流是对某一时间窗口内的请求数进行限制,保持系统的可用性和稳定性,防止因流量暴增而导致的系统运行缓慢或宕机。

常见的限流算法有:计数器算法,漏桶(Leaky Bucket)算法,令牌桶(Token Bucket)算法。

Spring Cloud Gateway官方提供了RequestRateLimiterGatewayFilterFactory过滤器工厂,使用Redis 和Lua脚本实现了 令牌桶 的方式。

令牌桶算法 是对漏桶算法的一种改进,漏桶算法能够限制请求调用的速率,而令牌桶算法能够在限制调用的平均速率的同时还允许一定程度的突发调用。在令牌桶算法中,存在一个桶,用来存放固定数量的令牌。算法中存在一种机制,以一定的速率往桶中放令牌。每次请求调用需要先获取令牌,只有拿到令牌,才有机会继续执行,否则选择选择等待可用的令牌、或者直接拒绝。

放令牌这个动作是持续不断的进行,如果桶中令牌数达到上限,就丢弃令牌。所以就存在这种情况,桶中一直有大量的可用令牌,这时进来的请求就可以直接拿到令牌执行,比如设置qps为100,那么限流器初始化完成一秒后,桶中就已经有100个令牌了,这时服务还没完全启动好,等启动完成对外提供服务时,该限流器可以抵挡瞬时的100个请求。所以,只有桶中没有令牌时,请求才会进行等待,最后相当于以一定的速率执行。

网上找了一个图:

2. 代码实战

上面已经提到过,Spring Cloud Gateway官方提供了RequestRateLimiterGatewayFilterFactory过滤器工厂,使用Redis 和Lua脚本实现了 令牌桶 的方式。

所以我们还需要引入 redis 的 reactive 依赖

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

application.yml 配置文件

server: port: 8080 spring: application: name: api-gateway redis: host: localhost port: 6379 password: cloud: gateway: routes: - id: cloud-gateway uri: http://192.168.1.211:8088/ predicates: - Path=/ytb/** filters: - StripPrefix=1 - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 1 # 令牌桶每秒填充速率 redis-rate-limiter.burstCapacity: 2 # 令牌桶总容量 key-resolver: "#{@pathKeyResolver}" # 使用 SpEL 表达式按名称引用 bean

在上面的配置文件,配置了 redis 的信息,并配置了 RequestRateLimiter 的限流过滤器,该过滤器需要配置三个参数:

burstCapacity,令牌桶总容量。replenishRate,令牌桶每秒填充平均速率。key-resolver,用于限流的键的解析器的 Bean 对象的名字。它使用 SpEL 表达式根据 #{@beanName} 从 Spring 容器中获取 Bean 对象。

编写URI限流规则配置类

@Configuration public class KeyResolverConfiguration { @Bean public KeyResolver pathKeyResolver(){ return exchange -> Mono.just(exchange.getRequest().getURI().getPath()); } }

然后本地启动一个 redis,重启项目,我们就可以测试看看效果了

还是原来的接口,在我们快速刷新了几次之后会发现返回HTTP ERROR 429

说明我们的限流起了作用了,同时限流成功看到 redis 中维护了两个键

request_rate_limiter.{file/getFileType}.timestamp request_rate_limiter.{xxx}.tokens

其他限流规则

参数限流:key-resolver: "#{@parameterKeyResolver}" (以下配置要求请求路径中必须携带 userId 参数)

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

IP限流:key-resolver: "#{@ipKeyResolver}"

@Bean public KeyResolver ipKeyResolver() { return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName()); } 过滤器规则(Filter) 过滤规则实例说明PrefixPath- PrefixPath=/app在请求路径前加上appRewritePath- RewritePath=/test, /app/test访问localhost:9022/test,请求会转发到localhost:8001/app/testSetPathSetPath=/app/{path}通过模板设置路径,转发的规则会在路径前增加app,{path}表示原请求路径RedirectTo重定向RemoveRequestHeader去掉某个请求头信息
StripRefix

StripPrefix 就表明截取路径的个数

spring: application: name: api-gateway cloud: gateway: routes: - id: cloud-gateway uri: http://192.168.1.211:8088 predicates: - Path=/ytb/my/** filters: - StripPrefix=2

这里就表示访问地址 http://localhost:8080/ytb/my/file/getFileType 会被转发到 http://192.168.1.211:8088/file/getFileType 地址。

跨域配置 spring: cloud: gateway: globalcors: corsConfigurations: '[/**]': allowedOriginPatterns: "*" allowed-methods: "*" allowed-headers: "*" allow-credentials: true exposedHeaders: "Content-Disposition,Content-Type,Cache-Control"

当然如果使用了 nginx 等配置代理来解决跨域,则可以不需要添加跨域支持。


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #gateway限流配置 #上一篇文章 #微服务系列服务网关 #Spring #Cloud #gateway #入门 #中我们学习了