高性能实现接口限流

防止用户恶意刷新接口,需要对用户限制访问
我们通过代码 添加对应的计算器,比如当某个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 协议》,转载必须注明作者和本文链接
讨论数量: 3

在业务代码使用redis结合lua脚本实现限流,不一样浸入应用了吗?直接上openresty,在web服务上限流,直接编写lua脚本引入不就好了。

3个月前 评论
唧唧复唧唧 (楼主) 3个月前

封装一下比较好

file

3个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
文章
1
粉丝
0
喜欢
1
收藏
1
排名:2644
访问:363
私信
所有博文
博客标签
社区赞助商