JAVA调用
private boolean checkAllowed(String routeId) {
RateLimiterConfig rateLimiterConfig = configMap.get(routeId);
int qps = rateLimiterConfig.getRate();
long now = System.currentTimeMillis();
String key = String.format(RATE_LIMITER_ITEM_KEY_PATTERN, routeId);
Object result = jedisTemplate.evalsha(rateLimiterScriptId, 1, key, String.valueOf(now), String.valueOf(qps));
return Integer.valueOf(result.toString()) > 0;
}
限流lua脚本
local key = KEYS[1]
local curTime = tonumber(ARGV[1])
local qps = tonumber(ARGV[2])
local millis = math.modf(1000 / qps)
local array = redis.call('hmget', key, 'curToken', 'lastTime')
local curToken = array[1]
local lastTime = array[2]
if (type(curToken) ~= 'string') then
curToken = 1
lastTime = curTime
redis.call('hmset', key, 'curToken', curToken, 'lastTime', lastTime)
else
curToken = tonumber(curToken)
lastTime = tonumber(lastTime)
end
local tokenToAdd = math.modf((curTime - lastTime) / millis)
local totalToken = curToken + tokenToAdd
local overload = false
if (totalToken > qps) then
totalToken = qps
overload = true
end
if (totalToken > 0) then
redis.call('hset', key, 'curToken', totalToken - 1)
if (tokenToAdd > 0) then
if (overload) then
lastTime = curTime
else
lastTime = lastTime + tokenToAdd * millis
end
redis.call('hset', key, 'lastTime', lastTime)
end
return 1
else
return 0
end