我想了解限速器是怎么工作的。
我在博客中看到的是:
public void makeApiCall(String ip){
Long currentTime=Timestamp timestamp = System.currentTimeMillis();
String key=ip+":"+currentTime;
Integer count=redisClient.get(key);
if(count!=null && count > 10){
throw LimitExceededException();
}
else{
redisClient.incr(key,1);
callApi();
}
}
到现在为止,我忽略了删除旧的钥匙。我不明白这个索伦是怎么工作的?正如上面所说,在多线程环境中,代码将在一秒钟内完成10个以上的api调用。它只能通过将redisclient.get(key)同步到callApi()代码来解决。
我从
假设在当前的第二个中已经服务了9个请求,现在同时出现了5个新的请求,所有这些新的线程在这5个线程中的任何一个执行“else”块之前调用redisclient.get(key)。因此,对于每个线程,计数将是9,else块将被执行,并且incr将被调用5次,对于每个线程,将调用api。
实际上,代码确实容易受到竞争条件(和内存膨胀,因为您没有考虑过期)的影响。解决这一问题的方法基本上有两种:使用watch
的multi/exec
事务,或者使用Lua脚本的eval
。
假设您使用Jedis作为Java客户机,那么类似于下面这样的操作就可以处理事务:
public void makeApiCall(String ip){
Long currentTime=Timestamp timestamp = System.currentTimeMillis();
String key=ip+":"+currentTime;
redisClient.watch(key);
Integer count=redisClient.get(key);
if(count!=null && count > 10){
throw LimitExceededException();
}
else{
Transaction t = redisClient.multi();
t.incr(key,1);
List<Object> resp = t.exec();
if(resp != null){
callApi();
}
}
}
Lua则是另一回事,但基本上假设您提供以下脚本(整个密钥名(ip+ts),只要您的代码在获得OK后继续使用callapi
,它就会执行同样的操作:
local count = redis.call('GET', KEYS[1])
if count and tonumber(count) > 10 then
return redis.error('count exceeded')
else
redis.call('INCR', KEYS[1])
redis.call('EXPIRE', KEYS[1], 10)
return 'OK'
end
注意,使用Lua您不需要观察更改,因为整个脚本是原子的。
最后,您在文档中提到的计数器模式似乎缺少watch
这一点--我已经提交了一个PR来纠正这一点(https://github.com/antirez/redis-doc/pull/888)。
我使用和来实施速率限制,例如每分钟5个请求: 然而,可以在最后一分钟发送5个请求,在第二分钟的第一秒发送5个请求,即在两秒钟内发送10个请求。 如何避免这个问题? 更新:我提出了这个清单。这是一个好方法吗?
我需要限制每分钟的请求数。我还没有找到任何方法来使用Spring云网关redis。下面是当前的实现:图像实现 customRouter.getBurstCapacitycustomRouter.getReplenishRate 两者都仅在几秒钟内运行。示例:20 个请求在同一秒内与。 我在1分钟内需要20个请求。
我不能玩春云之门的限速器。我在这里配置网关: 我使用JMeter调用API循环1000次,但网关没有响应429响应中的请求太多。我哪里错了?
我正在使用PHP作为我的webservice的后端,我需要webservice能够设置一个速率限制,在过去24小时内,基于用户的PHP会话,最多1000个请求。这是不是可以做到这一点,而不使用数据库和只是速率限制,只使用PHP。我目前已经为每个会话每秒1个请求设置了速率限制器,但我希望在过去24小时内为每个会话设置1000个请求的速率限制。因为我是PHP的新手,任何帮助都会很好。 这里是我为每秒1
我正在使用ProjectReactor使用rest从web服务加载数据。这是与多个线程并行完成的。我开始达到web服务的速率限制,因此我希望每秒最多发送10个请求,以避免出现这些错误。用Reactor我该怎么做? 使用zipWith(Mono.delayMillis(100))?还是有更好的办法? 非常感谢。
速率限制配置参考 filter.http.RateLimit filter.http.RateLimit proto { "domain": "...", "stage": "...", "request_type": "...", "timeout": "{...}" } domain (string, REQUIRED) 需要调用速率限制服务时的域。 stage (uint3