高性能实现接口限流
防止用户恶意刷新接口,需要对用户限制访问
我们通过代码 添加对应的计算器,比如当某个IP 1分钟内请求超过60次 那我们就可以阻止访问
然而只通过应用代码层方面的操作 仍然有瑕疵,比如仅通过redis设置key值自增 也会涉及到多次访问redis 造成不必要的网络开销,也不可保证原子性 有可能会造成误杀的情况
Redis从2.6版本开始支持Lua脚本,通过这种方式可以保证操作的原子性,并且只存在一次和redis的网络交互
$redis = new \Redis();
$redis->connect('127.0.0.1');
$redis->select(2);
try {
$script = <<<EOF
local success, result = pcall(function()
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local current = tonumber(redis.call('get',key) or "0")
if current +1 > limit then
return 0
else
redis.call("INCRBY", key, 1)
redis.call("EXPIRE", key, 1)
return redis.call('get',key) or "0"
end
end)
if success then
return result
else
return 'Error: ' .. result
end
EOF;
$key1 = $_SERVER['REMOTE_ADDR'];
$value1 = 20;
$result = $redis->eval($script,[$key1,$value1], 1);
var_dump($result);
}catch (\RedisException $e) {
var_dump($e->getMessage());
}
上述示例实现了 1S内单IP 限制最高20的访问
本作品采用《CC 协议》,转载必须注明作者和本文链接
在业务代码使用redis结合lua脚本实现限流,不一样浸入应用了吗?直接上openresty,在web服务上限流,直接编写lua脚本引入不就好了。
封装一下比较好