1.背景在我们正常的开发过程中,一般一个请求需要经过多个微服务,例如:一个请求从服务A流向服务B,如果服务A请求速度太快,如果B服务响应慢,难免会导致系统出现问题。因为,我们需要有限的流操作。2.实现函数提供自定义限流密钥生成,需要实现KeyResolver接口。提供默认限流算法,实现RateLimiter接口。当限流键为空时,不直接限流,释放路由。参数spring.cloud.gateway.routes[x].filters[x].args[x].deny-empty-key用于控制限流时返回给客户。端对应的代码由spring.cloud.gateway.routes[x].filters[x].args[x].status-code控制,这个org.springframework.http.HttpStatus类的枚举值需要被写。RequestRateLimiter只能使用名称||配置args,不是速记。RequestRateLimiter过滤器的redis-rate-limiter参数在RedisRateLimiter的CONFIGURATION_PROPERTY_NAME属性中配置。在施工方法中使用。3.网关层限流的key生成规则,默认是PrincipalNameKeyResolver来实现限流算法,默认是RedisRateLimiter来实现,就是令牌桶算法。1、使用默认的redis进行限流。SpringCloudGateway中默认提供了RequestRateLimiter过滤器来实现限流操作。1、引入jar包com.alibaba.cloudspring-cloud-starter-alibaba-nacos-discoveryorg.springframework.cloudspring-cloud-starter-gatewayorg.springframework.cloudspring-cloud-复制代码启动器负载平衡器org.springframework.bootspring-boot-starter-data-redis-reactiveorg.projectlomboklombok2、编写配置文件弹簧:应用程序:名称:网关-9205云:nacos:发现:服务器地址:本地主机:8847网关:路由:-id:user-provider-9206uri:lb://user-provider-9206谓词:-Path=/user/**filters:-RewritePath=/user(?/?.*),$\{segment}-name:RequestRateLimiterargs:#如果返回的key为空,则没有限流deny-empty-key:false#每秒产生多少个tokenredis-rate-limiter.replenishRate:1#1秒内最大的token,即1s内可以允许的burst进程,设置为0,表示阻塞所有Requestredis-rate-limiter.burstCapacity:1#每个请求申请几个tokenredis-rate-limiter.requestedTokens:1redis:host:192.168.7.1database:12port:6379password:123456server:port:9205debug:true3,gatewaynormalresponse4、网关限流response2、自定义限流算法和限流key1、自定义限流key写一个类实现KeyResolver接口包com.huan.study.gateway;导入lombok.extern.slf4j.Slf4j;导入org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;导入org.springframework.cloud.gateway.route.Route;导入org.springframework.cloud.gateway.support.ServerWebExchangeUtils;导入org.springframework.http.server.reactive.ServerHttpRequest;导入org.springframework.stereotype.Component;导入org.springframework.web.server.ServerWebExchange;导入reactor.core.publisher.Mono;importjava.util.Optional;/***限制流的密钥获取**@authorhuan.fu2021/9/7-上午10:25*/@Slf4j@ComponentpublicclassDefaultGatewayKeyResolverimplementsKeyResolver{@OverridepublicMonoresolve(ServerWebExchangeexchange){//获取当前路径由Routeroute=exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);ServerHttpRequest请求=exchange.getRequest();Stringuri=request.getURI().getPath();log.info("当前返回的uri:[{}]",uri);返回Mono.just(Optional.ofNullable(route).map(Route::getId).orElse("")+"/"+uri);}}配置文件中的写法(部分)spring:cloud:gateway:routes:-id:user-provider-9206filters:-name:RequestRateLimiterargs:#returnkeyforratelimitingkey-resolver:"#{@defaultGatewayKeyResolver}"2.编写自定义限速算法实现RateLimiter,这里使用内存限流包com.huan.study.gateway;importcom.google.common.collect.Maps;importcom.google.common。util.concurrent.RateLimiter;导入lombok.Getter;导入lombok.Setter;导入lombok.ToString;导入lombok.extern.slf4j.Slf4j;导入org.springframework.cloud.gateway.filter.ratelimit.AbstractRateLimiter;导入org.springframework。cloud.gateway.support.ConfigurationService;importorg.springframework.context.annotation.Primary;importorg.springframework.stereotype.Component;importreactor.core.publisher.Mono;/***@authorhuan.fu2021/9/上午7-10:36*/@Component@Slf4j@PrimarypublicclassDefaultGatewayRateLimiterextendsAbstractRateLimiter{/***和配置文件中的配置属性对应*/privatestaticfinalStringCONFIGURATION_PROPERTY_NAME="default-gateway-rate-limiter";私有RateLimiterrateLimiter=RateLimiter.create(1);protectedDefaultGatewayRateLimiter(ConfigurationServiceconfigurationService){super(DefaultGatewayRateLimiter.Config.class,CONFIGURATION_PROPERTY_NAME,configurationService);}@OverridepublicMonoisAllowed(StringrouteId,Stringid){log.info("网络默认的限制流routeId:[{}],id:[{}]",routeId,id);配置config=getConfig().get(routeId);returnMono.fromSupplier(()->{booleanacquire=rateLimiter.tryAcquire(config.requestedTokens);if(acquire){returnnewResponse(true,Maps.newHashMap());}else{returnnewResponse(false,Maps.newHashMap());}});}@Getter@Setter@ToStringpublicstaticclassConfig{/***每次请求多少令牌*/privateIntegerrequestedTokens;}}配置文件中的写法(部分)spring:cloud:gateway:routes:-id:user-provider-9206filters:-name:RequestRateLimiterargs:#Customrate-limiterrulerate-limiter:"#{@defaultGatewayRateLimiter}"注意??:该类注解需要加上@Primary3.配置文件中写spring:application:name:gateway-9205cloud:nacos:discovery:server-addr:localhost:8847gateway:routes:-id:user-provider-9206uri:lb://user-provider-9206谓词:-Path=/user/**过滤器:-RewritePath=/user(?/?.*),$\{segment}-name:RequestRateLimiterargs:#Customrate-limiter:"#{@defaultGatewayRateLimiter}"#返回限流的keykey-resolver:"#{@defaultGatewayKeyResolver}"#如果返回的key为空,则不限流deny-empty-key:false#限流后的响应返回给客户端的code是429,请求过多status-code:TOO_MANY_REQUESTS#每个请求申请多个token。default-gateway-rate-limiter的值定义在defaultGatewayRateLimiter中。default-gateway-rate-limiter.requestedTokens:1server:port:9205debug:true4.完成代码https://gitee.com/huan1993/spring-cloud-alibaba-parent/tree/master/gateway-redis-limiter5.参考文档1,https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-redis-ratelimiter