图9-3NginxLua分布式计数器限流案例架构

分布式计数器限流

分布式计算器的限流是利用Redis来存储限流关键字key的统计计数。

这里有两种限流实现:Nginx Lua分布式计数器限流和RedisLua分布式计数器限流。

实战:Nginx Lua分布式计数器限流

本节以用户IP计数器的限流功能为例,实现单个IP在一定时间段内只能访问一定次数(如10次)的限流功能(如10 秒)。由于Redis是用来存储分布式访问计数的,所有功能都是通过Nginx Lua编程完成的,所以这种限流方式称为Nginx Lua分布式计数器限流。

本节Nginx Lua分布式计数器限流案例的架构如图9-3所示。

图9-3 Nginx Lua分布式计数器限流架构

首先介绍限流计数器脚本RedisKeyRateLimiter.lua,它负责完成访问计数和限流结果判断,其中涉及到Redis存储访问,具体代码如下:

以上代码位于练习项目LuaDemoProject中

在src/luaScript/module/ratelimit/文件夹下,文件名为access_auth_nginx.lua。 access_auth_nginx.lua在拼接计数器的key时使用Nginx的内置变量$remote_addr获取客户端的IP地址,最后将访问计数的key按如下格式存储在Redis中:

192.168.233.1这里是作者的本地测试IP,这个IP存储在Redis中的限流计数结果如图9-4所示。

图 9-4 此 IP 存储在 Redis 中的当前限制计数结果

在Nginx的访问请求处理阶段,使用access_auth_nginx.lua脚本限制请求流量的配置代码如下:

以上配置位于练习项目LuaDemoProject的src/conf/nginxratelimit.conf文件中。生效前需要替换openresty-start.sh脚本中的配置文件,然后重启Nginx。

接下来,开始限流自验证。

在上面的代码中,由于RedisKeyRateLimiter设置的限流规则是单个IP​​在10秒内限制访问10次,所以在验证时8位可逆计数器设计代码,浏览器刷新10次后限流。在浏览器中输入以下测试地址:

10秒内连续刷新,第6次输出如图9-5所示。

图 9-5 自验证时第 6 次刷新的输出

10 秒内持续刷新。发现第10次后请求被限制,说明Lua限流脚本工作正常,限流后的输出如图9-6所示。

图 9-6 自验证时刷新 10 次后的输出

上面的代码有两个缺陷:

(1)数据一致性问题:计数器的读取和自增是由两个Redis远程操作完成的,如果有多个网关同时限流,可能会出现数据一致性问题。

p>

(2)性能问题:同样的限流操作需要多次访问Redis,并且有多次网络传输,大大降低了限流性能。

实战:Redis Lua分布式计数器限流

众所周知,Redis 允许将 Lua 脚本加载到 Redis 服务器中执行,并且可以调用大部分 Redis 命令,并且 Redis 保证了脚本的原子性。由于Redis是用来存储分布式访问计数的,而限流计数器的Lua脚本是通过Redis来执行的8位可逆计数器设计代码,所以这种限流方式称为RedisLua分布式计数器限流。

本节Redis Lua分布式计数器限流案例的架构如图9-7所示。

图9-7 Redis Lua分布式计数器限流架构

首先我们看一下限流计数器脚本redis_rate_limiter.lua。该脚本负责完成对访问计数和限流结果的判断,其中会涉及到Redis计数的存储访问。需要注意的是,脚本将在 Redis 中加载和执行。

计数器脚本redis_rate_limiter.lua的代码如下:

以上代码位于练习项目LuaDemoProject中

在src/luaScript/module/ratelimit/文件夹下,文件名为redis_rate_limiter.lua。在调用该脚本之前,必须先将其加载到Redis中,并获取加载后的sha1代码,供Nginx上的限流脚本access_auth_evalsha.lua使用。

将redis_rate_limiter.lua加载到Redis中的Linux shell命令如下:

然后看access_auth_evalsha.lua限流脚本,它使用Redis的evalsha操作命令远程访问Redis上加载的redis_rate_limiter.lua访问计算器脚本,完成对同一IP的限流操作。

access_auth_evalsha.lua限流脚本代码如下:

以上代码位于练习项目LuaDemoProject中

在src/luaScript/module/ratelimit/文件夹中,文件名为access_auth_evalsha.lua。在Nginx的访问请求处理阶段,使用access_auth_evalsha.lua脚本限制请求流量的配置如下:

以上配置位于练习项目LuaDemoProject中

在src/conf/nginx-ratelimit.conf文件中,需要替换openresty-start.sh脚本中的配置文件才能生效,然后重启Nginx。

然后启动限流自验证。在浏览器中访问以下地址:

10 秒内持续刷新。发现请求在第10次后被限流,说明Redis内部的Lua限流脚本工作正常,限流后的输出如图9-8所示。

图 9-8 自验证时刷新 10 次后的输出

通过将Lua脚本加载到Redis中执行有以下优点:

(1)减少网络开销:不使用Lua的代码需要向Redis发送多个请求,而脚本只需要一次,减少网络传输。

(2)原子操作:Redis将整个脚本作为一个原子执行,无需担心并发,无事务。

(3)重用:只要不重启Redis,脚本加载后会一直缓存在Redis中,其他客户端可以通过sha1编码执行。

本文讲解的内容是高并发核心编程、限流原理与实战、分布式计数器限流

下一篇会讲解高并发核心编程、限流原理和实战,详细讲解Nginx漏桶限流;

觉得文章不错的朋友可以转发这篇文章关注小编;

感谢您的支持!

这篇文章是我希望天上没有虫子分享给大家的。如果你有什么要分享的,你可以分享。想了解更多,可以在微信公众号找我。我会等你的。

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论