浅谈Nginx 中的两种限流方式
浅谈Nginx 中的两种限流方式
在高并发的场景下,为了保证系统的稳定性和可用性,我们需要对请求进行限流处理。Nginx 作为一款高性能的反向代理和 Web 服务器,也提供了多种限流的方式。本文主要介绍 Nginx 中的两种限流方式:ngx_http_limit_req_module 和 ngx_http_limit_conn_module。
ngx_http_limit_req_module
ngx_http_limit_req_module 模块基于令牌桶算法实现,可以让 Nginx 对接口请求进行速率限制,达到防止爬虫或定时任务产生的大量请求拦截。
开启限流
使用 limit_req_zone 指令配置共享内存区域,指定限制请求速率所需要的参数,如下:
http {
limit_req_zone $binary_remote_addr zone=limit:10m rate=10r/s;
}
这里创建了大小为 10MB 的共享内存区域,用来限制 $binary_remote_addr 唯一标识的客户端的请求速率为 10r/s。
在 server 或 location 块中使用 limit_req 指令启用限流,如下:
location /api {
limit_req zone=limit burst=20 nodelay;
proxy_pass http://upstream_server;
}
这里限制 /api 路径的请求速率,同时使用 burst 参数来保存一部分出现峰值请求时依然允许访问(如最开始接受1000个并发的请求,当第1001个请求访问时,它会等待,之后在一秒钟内的20个以内的请求是允许的),使用 nodelay 参数来让请求在达到限流时立即错误返回。
限流错误信息
当达到限流时,Nginx 会返回制定的限流错误信息。可以使用如下配置来制定错误信息:
http {
limit_req_zone $binary_remote_addr zone=limit:10m rate=10r/s;
limit_req_status 429;
limit_req_log_level debug;
limit_req_log_zone rate_limit_log;
}
server {
location /api {
limit_req zone=limit burst=20 nodelay;
limit_req_status 444;
limit_req_log_rate 1;
limit_req_log_rate_after 1m;
limit_req_log_level info;
limit_req_log_zone rate_limit_log;
proxy_pass http://upstream_server;
}
}
这里使用 limit_req_status 配置错误状态码,使用 limit_req_log_level 配置日志等级,使用 limit_req_log_zone 配置日志存储区域。日志可以提供限流的详细信息,并帮助分析限流情况。
ngx_http_limit_conn_module
与 ngx_http_limit_req_module 不同,ngx_http_limit_conn_module 模块基于连接数限制请求速率,常用于限制来自同一 IP 地址的并发请求。
开启限流
使用 limit_conn_zone 指令配置共享内存区域,指定连接数限制所需要的参数,如下:
http {
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
}
这里创建了大小为 10MB 的共享内存区域,用来限制 $binary_remote_addr 唯一标识的客户端的连接数。
在 server 或 location 块中使用 limit_conn 指令启用限流,如下:
location /api {
limit_conn conn_limit 10;
proxy_pass http://upstream_server;
}
这里限制 /api 路径的并发连接数不能超过 10 个。
限流错误信息
与 ngx_http_limit_req_module 类似,使用 limit_conn_status 和 limit_conn_log_level 参数来配置连接数限制错误状态码和日志等级,使用 limit_conn_log_zone 指令来配置共享内存日志区域。通常与一些防火墙配合使用,用户若是用了代理服务器,则可以伪造ip来增大攻击强度。所以该模式有一定的缺陷,需要考虑更多情况。
综上所述,ngx_http_limit_req_module 更适合限制请求速率;ngx_http_limit_conn_module 更适合限制连接数。在实际使用时,可以根据自身情况结合使用。
