Nginx限流实践
发布于2024-12-07 19:38:40,更新于2024-12-07 22:06:06,标签:devops 文章会持续修订,转载请注明来源地址:https://meethigher.top/blog一、限流
之前我有记录通过CentOS7定时任务实现的Nginx限流功能。这算是通过Nginx进行限流的一种思路。
还有另外一种思路,是通过Nginx内置的两个模块来实现。
- limit_req: 用于限制每秒的请求次数。该模块基于令牌桶(Token Bucket)算法,每个请求在处理前必须从令牌桶中获取一个令牌,如果没有令牌可用,则请求被延迟或拒绝。
- limit_conn: 用于限制同时连接数。该模块控制每个特定键(如IP地址或用户)允许的最大并发连接数。
1.1 limit_req
若需要查看详细内容,自行查阅Module ngx_http_limit_req_module
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
定义一个10MB的内存区域,命名为one,用来存储客户端IP地址的调用数,限制每个客户端每秒只能调用1次。注意nginx是以毫秒为单位的。当配置了2r/s
时,平均下来就是每500ms
内,只允许成功1个请求。
limit_req zone=one burst=5 nodelay;
使用one空间,限制同一个键调用时,支持5个突发请求,并且配置nodelay表示立即响应。
limit_req可以配置在http、server、location内。
若未配置nodelay,则表示进行延迟处理,当超过请求速率rate
时,多余的请求会进入突发队列(长度由 burst
决定)。Nginx 会根据配置的rate
,以固定时间间隔从队列中取出请求进行处理。例如:
rate=1r/s
意味着每 1000ms 处理一个请求。- 如果一个客户端在 1 秒内发送了 6 个请求:
- 前 1 个请求按速率直接处理。
- 剩下的 5 个请求将进入突发队列并被延迟。
- 每隔 1000ms,处理队列中的一个请求,持续 5000ms。
当未配置nodelay时,持续 5000ms 会间接影响到后续的在rate内请求的响应速率。
配置示例
1 | worker_processes 2; |
以上示例,在高并发调用时,实际情况前6次立马成功,后续每隔1秒成功1个请求,其他请求均返回429状态码。该结果可以使用JMeter来进行验证。
1.2 limit_conn
若需要查看详细内容,自行查阅Module ngx_http_limit_conn_module
limit_conn_zone $binary_remote_addr zone=two:10m;
定义一个10MB的内存区域,命名为two,用来存储客户端IP地址的连接数。
limit_conn two 1;
使用two空间,限制同一个键,同时刻最多只有1个连接。
准备一个10秒才会响应的后端服务http://10.0.0.1:4321
。
示例配置
1 | worker_processes 2; |
以上示例,在1000个请求连接时,只有1个连接成功,其他请求均返回409状态码。该结果可以使用JMeter来进行验证。
二、参考
Module ngx_http_limit_req_module