当前位置: 首页 > 后端技术 > Java

springcloudgateway使用redis限流观察

时间:2023-04-02 09:23:41 Java

引入redis的reactive依赖org.springframework.bootspring-boot-starter-data-redis-reactive2.6.2定义限流的具体维度@ConfigurationpublicclassDemoConfiguration{@BeanpublicKeyResolverpathKeyResolver(){returnexchange->Mono.just(exchange.getRequest().getPath().toString());}}两种方式,一种是在application.yml中配置spring:redis:host:127.0.0.1port:6379cloud:gateway:routes:-id:routeBuri:http://www.b.compredicates:-Path=/pathBfilters:-name:RequestRateLimiterargs:#平均每秒处理多少请求redis-rate-limiter.replenishRate:2#一秒内允许完成的最大请求numberredis-rate-limiter.burstCapacity:2#获取Bean对象,@BeanID,默认bean名与方法名相同。key-resolver:"#{@apiKeyResolver}"另一个是在RouteDefinitionRepository的实现中,即在动态路由FilterDefinition的实现中filter3=newFilterDefinition();filter3.setName("RequestRateLimiter");Mapmap3=newHashMap<>();map3.put("redis-rate-limiter.replenishRate","3");map3.put("redis-rate-limiter.burstCapacity","2");map3.put("key-resolver","#{@pathKeyResolver}");filter3.setArgs(map3);可以在本地redis中使用monitor命令观察执行内容127.0.0.1:6379>monitorOK然后看同一秒连续执行两个请求的情况:1643107233.014412[0127.0.0.1:52263]"EVALSHA"“76a566c51f92d8f643d16e0ef0101663d5380dba”“2”“request_rate_limiter.{/client1}.tokens”“request_rate/timeclimiter.tokens”“request_rate/timeclimiter.”“”“1”1643107233.014451[0lua]“TIME”134301724“TIME”134301724“request_rate_limiter.{/client1}.tokens"1643107233.014469[0lua]"get""request_rate_limiter.{/client1}.timestamp"1643107233.014484[0lua]"setex""request_rate_limiter.{/client1}.tokens""2""1"1643107233.014495[0lua]"setex""request_rate_limiter.{/client1}.timestamp""2""1643107233"1643107233.326166[0127.0.0.1:52263]"EVALSHA""76a566c51f92d8f643d16e0ef0101663d5380dba""2""request_rate_limiter.{/client1}.tokens""request_rate_limiter.{/client1}.timestamp""2""2""""1"1643107233.326219[0lua]"TIME"1643107233.326228[0lua]"get""request_rate_limiter.{/client1}.tokens"1643107233.326235[0lua]“get”“request_rate_limiter.{/client1}.timestamp”1643107233.326251[0lua]“setex”“request_rate_limiter.{/client1}.tokens”“2”“0”1643107233.326262[0lua]“setex”"request_rate_limiter.{/client1}.timestamp""2""1643107233"再看一下同一秒内连续三次的情况:1643107474.188667[0127.0.0.1:52263]"EVALSHA""76a566c51f92d8f643d16e0ef0101663d5380dba""2""request_rate_limiter.{/谎言nt1}.tokens""request_rate_limiter.{/client1}.timestamp""2""2""""1"1643107474.188704[0lua]"TIME"1643107474.188712[0lua]"get""request_rate_limiter.{/client1}.令牌“1643107474.188718[0lua]“get”“request_rate_limiter.{/client1}.timestamp”1643107474.188733[0lua]“setex”“request_rate_limiter.{/client1}.tokens”“2”“1”1643107474.188745[0lua]“setEx“”request_rate_limiter。{/client1}.timestamp“”2“”1643107474“1643107444.347245[0127.0.0.0.1:52263]/client1}.timestamp""2""2""""1"1643107474.347283[0lua]"TIME"1643107474.347291[0lua]"get""request_rate_limiter.{/client1}.tokens"1643107474.347298[0lua]"get""request_rate_limiter.{/client1}.timestamp"1643107474.347313[0lua]"setex""request_rate_limiter.{/client1}.tokens""2""0"1643107474.347324[0lua]"setex""request_rate_limiter.{/client1}.时间戳“”2""1643107474"1643107474.494758[0127.0.0.1:52263]"EVALSHA""76a566c51f92d8f643d16e0ef0101663d5380dba""2""request_rate_limiter.{/client1}.tokens""request_rate_limiter.{/client1}.tokens""request_rate_limiter.{/client1}.tokens""request_2"client_limiter."request_2"client_limiter."""1"1643107474.494793[0lua]"TIME"1643107474.494801[0lua]"get""request_rate_limiter.{/client1}.tokens"1643107474.494808[0lua]"get""request_rate_limiter".{/client1}.timest40lua]"setex""request_rate_limiter.{/client1}.tokens""2""0"1643107474.494834[0lua]"setex""request_rate_limiter.{/client1}.timestamp""2""1643107474"第三次请求了被限制,返回HTTP代码429执行的lua脚本,具体内容可以看源码:redis.replicate_commands()localtokens_key=KEYS[1]localtimestamp_key=KEYS[2]localrate=tonumber(ARGV[1])localcapacity=tonumber(ARGV[2])localnow=redis.call('TIME')[1]localrequested=tonumber(ARGV[4])localfill_time=capacity/ratelocalttl=math.floor(fill_time*2)locallast_tokens=tonumber(redis.call("get",tokens_key))iflast_tokens==nilthenlast_tokens=capacityendlocallast_refreshed=tonumber(redis.call("get",timestamp_key))iflast_refreshed==nilthenlast_refreshed=0endlocaldelta=math.max(0,now-last_refreshed)localfilled_tokens=math.min(容量,last_tokens+(delta*rate))localallowed=filled_tokens>=requestedlocalnew_tokens=filled_tokenslocalallowed_num=0ifallowedthennew_tokens=filled_tokens-requestedallowed_num=1endifttl>0thenredis.call("setex",tokens_key,ttl,new_tokens)redis.call("setex",timestamp_key,ttl,now)endreturn{allowed_num,new_tokens}

最新推荐
猜你喜欢