Spring Cloud Gateway 网关限流

网友投稿 312 2022-09-26

Spring Cloud Gateway 网关限流

Spring Cloud Gateway 限流

​​一、背景​​​​二、实现功能​​​​三、网关层限流​​

​​1、使用默认的redis来限流​​

​​1、引入jar包​​​​2、编写配置文件​​​​3、网关正常响应​​​​4、网关限流响应​​

​​2、自定义限流算法和限流key​​

​​1、自定义限流key​​​​2、自定义限流算法​​​​3、配置文件中的写法​​

​​四、完成代码​​​​五、参考文档​​

一、背景

在我们平时开发过程中,一般一个请求都是需要经过多个微服务的,**比如:**请求从A服务流过B服务,如果A服务请求过快,导致B服务响应慢,那么必然会导致系统出现问题。因为,我们就需要有限流操作。

二、实现功能

三、网关层限流

限流的key 生成规则,默认是 ​​PrincipalNameKeyResolver​​​来实现 限流算法,默认是 ​​​RedisRateLimiter​​来实现,是令牌桶算法。

1、使用默认的redis来限流

在​​Spring Cloud Gateway​​​中默认提供了 ​​RequestRateLimiter​​ 过滤器来实现限流操作。

1、引入jar包

com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery org.springframework.cloud spring-cloud-starter-gateway org.springframework.cloud spring-cloud-starter-loadbalancer org.springframework.boot spring-boot-starter-data-redis-reactive org.projectlombok lombok

2、编写配置文件

spring: application: name: gateway-9205 cloud: nacos: discovery: server-addr: localhost:8847 gateway: routes: - id: user-provider-9206 uri: lb://user-provider-9206 predicates: - Path=/user/** filters: - RewritePath=/user(?/?.*), $\{segment} - name: RequestRateLimiter args: # 如果返回的key是空的话,则不进行限流 deny-empty-key: false # 每秒产生多少个令牌 redis-rate-limiter.replenishRate: 1 # 1秒内最大的令牌,即在1s内可以允许的突发流程,设置为0,表示阻止所有的请求 redis-rate-limiter.burstCapacity: 1 # 每次请求申请几个令牌 redis-rate-limiter.requestedTokens: 1 redis: host: 192.168.7.1 database: 12 port: 6379 password: 123456server: port: 9205debug: true

3、网关正常响应

4、网关限流响应

2、自定义限流算法和限流key

1、自定义限流key

编写一个类实现 KeyResolver 接口即可。

package com.huan.study.gateway;import lombok.extern.slf4j.Slf4j;import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;import org.springframework.cloud.gateway.route.Route;import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;import org.springframework.org.springframework.stereotype.Component;import org.springframework.web.server.ServerWebExchange;import reactor.core.publisher.Mono;import java.util.Optional;/** * 限流的key获取 * * @author huan.fu 2021/9/7 - 上午10:25 */@Slf4j@Componentpublic class DefaultGatewayKeyResolver implements KeyResolver { @Override public Mono resolve(ServerWebExchange exchange) { // 获取当前路由 Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR); ServerHttpRequest request = exchange.getRequest(); String uri = request.getURI().getPath(); log.info("当前返回的uri:[{}]", uri); return Mono.just(Optional.ofNullable(route).map(Route::getId).orElse("") + "/" + uri); }}

配置文件中的写法(部分)

spring: cloud: gateway: routes: - id: user-provider-9206 filters: - name: RequestRateLimiter args: # 返回限流的key key-resolver: "#{@defaultGatewayKeyResolver}"

2、自定义限流算法

编写一个类实现 RateLimiter ,此处使用内存限流

package com.huan.study.gateway;import com.google.common.collect.Maps;import com.google.common.util.concurrent.RateLimiter;import lombok.Getter;import lombok.Setter;import lombok.ToString;import lombok.extern.slf4j.Slf4j;import org.springframework.cloud.gateway.filter.ratelimit.AbstractRateLimiter;import org.springframework.cloud.gateway.support.ConfigurationService;import org.springframework.context.annotation.Primary;import org.springframework.stereotype.Component;import reactor.core.publisher.Mono;/** * @author huan.fu 2021/9/7 - 上午10:36 */@Component@Slf4j@Primarypublic class DefaultGatewayRateLimiter extends AbstractRateLimiter { /** * 和配置文件中的配置属性相对应 */ private static final String CONFIGURATION_PROPERTY_NAME = "default-gateway-rate-limiter"; private RateLimiter rateLimiter = RateLimiter.create(1); protected DefaultGatewayRateLimiter(ConfigurationService configurationService) { super(DefaultGatewayRateLimiter.Config.class, CONFIGURATION_PROPERTY_NAME, configurationService); } @Override public Mono isAllowed(String routeId, String id) { log.info("网关默认的限流 routeId:[{}],id:[{}]", routeId, id); Config config = getConfig().get(routeId); return Mono.fromSupplier(() -> { boolean acquire = rateLimiter.tryAcquire(config.requestedTokens); if (acquire) { return new Response(true, Maps.newHashMap()); } else { return new Response(false, Maps.newHashMap()); } }); } @Getter @Setter @ToString public static class Config { /** * 每次请求多少个 token */ private Integer requestedTokens; }}

配置文件中的写法(部分)

spring: cloud: gateway: routes: - id: user-provider-9206 filters: - name: RequestRateLimiter args: # 自定义限流规则 rate-limiter: "#{@defaultGatewayRateLimiter}"

注意⚠️: 这个类需要加上 ​​​@Primary​​ 注解。

3、配置文件中的写法

spring: application: name: gateway-9205 cloud: nacos: discovery: server-addr: localhost:8847 gateway: routes: - id: user-provider-9206 uri: lb://user-provider-9206 predicates: - Path=/user/** filters: - RewritePath=/user(?/?.*), $\{segment} - name: RequestRateLimiter args: # 自定义限流规则 rate-limiter: "#{@defaultGatewayRateLimiter}" # 返回限流的key key-resolver: "#{@defaultGatewayKeyResolver}" # 如果返回的key是空的话,则不进行限流 deny-empty-key: false # 限流后向客户端返回的响应码429,请求太多 status-code: TOO_MANY_REQUESTS # 每次请求申请几个令牌 default-gateway-rate-limiter 的值是在 defaultGatewayRateLimiter 中定义的。 default-gateway-rate-limiter.requestedTokens: 1server: port: 9205debug: true

四、完成代码

​​https://gitee.com/huan1993/spring-cloud-alibaba-parent/tree/master/gateway-redis-limiter​​

五、参考文档

1、​​https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-redis-ratelimiter​​

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:营销头条:王菲的每一次代言,都是一次时尚的洗牌!
下一篇:springcloud整合seata
相关文章

 发表评论

暂时没有评论,来抢沙发吧~