注意: 本文内容于 2024-12-07 19:38:40 创建,可能不会在此平台上进行更新。如果您希望查看最新版本或更多相关内容,请访问原文地址:Nginx限流实践。感谢您的关注与支持!
一、限流
之前我有记录通过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内请求的响应速率。
配置示例
worker_processes 2;
error_log logs/error.log;
events {
worker_connections 4096;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main
'$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
sendfile on;
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
limit_req_status 429;
server {
listen 80;
location / {
limit_req zone=one burst=5 nodelay;
root html;
}
}
}
以上示例,在高并发调用时,实际情况前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
。
示例配置
worker_processes 2;
error_log logs/error.log;
events {
worker_connections 4096;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main
'$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
sendfile on;
limit_conn_zone $binary_remote_addr zone=two:10m;
limit_conn_status 409;
server {
listen 80;
location / {
limit_conn two 1;
proxy_pass http://10.0.0.1:4321;
}
}
}
以上示例,在1000个请求连接时,只有1个连接成功,其他请求均返回409状态码。该结果可以使用JMeter来进行验证。
二、参考
Module ngx_http_limit_req_module
Module ngx_http_limit_conn_module
Nginx限流功能优化:让流量控制变得轻松简单