为什么要限制Nginx连接数
服务器资源有限,如果不做连接数控制,一个恶意用户就能用大量并发连接把服务器资源占满,导致正常用户无法访问。CC攻击就是利用这个弱点——用大量连接请求拖垮服务器。Nginx的limit_conn模块就是专门解决这个问题的,它能按IP(或其他key)限制同时连接数,从源头控制并发。
limit_conn_zone指令:定义共享内存区
限制连接数之前,先用limit_conn_zone定义一个共享内存区域,用来记录每个key的连接计数。
语法:
limit_conn_zone zone=名称:大小;
关键参数说明:
:作为限制依据的变量,最常用的是(二进制格式的客户端IP),比更省内存zone=名称:大小:共享内存区名称和大小,10m大约可以记录16万个IP的连接状态
配置位置:http块内(不能放在server或location中)
http {
limit_conn_zone zone=connlimit:10m;
}
limit_conn指令:设置连接数上限
定义好共享内存区后,在server或location块中用limit_conn设置具体限制。
语法:
limit_conn zone名称 连接数;
完整示例:
http {
limit_conn_zone zone=connlimit:10m;
server {
listen 80;
server_name example.com;
# 每个IP最多20个并发连接
limit_conn connlimit 20;
location / {
proxy_pass http://backend;
}
# 下载区域限制更严格
location /download/ {
limit_conn connlimit 5;
root /data/files;
}
}
}
注意:location中的limit_conn会覆盖server层的设置,不是叠加。
limit_conn与limit_req的区别
很多人搞混这两个模块,简单区分:
- limit_conn:限制同时在线的连接数,比如一个IP最多保持20个连接
- limit_req:限制单位时间内的请求数,比如一个IP每秒最多10个请求
两者配合使用效果最好:limit_conn控制并发连接,limit_req控制请求速率。
http {
limit_conn_zone zone=connlimit:10m;
limit_req_zone zone=reqlimit:10m rate=10r/s;
server {
limit_conn connlimit 20;
limit_req reqlimit burst=20 nodelay;
}
}
自定义503错误页面
连接数超限时,Nginx默认返回503状态码。可以自定义错误页面,给用户更友好的提示:
limit_conn_status 503;
server {
limit_conn connlimit 20;
limit_conn_status 503;
error_page 503 /503.html;
location = /503.html {
root /usr/share/nginx/html;
internal;
}
}
连接数限制日志记录
默认情况下,连接被限制时Nginx会在error日志中记录一条信息。日志级别可以通过limit_conn_log_level调整:
# 可选值:info | notice | warn | error(默认warn)
limit_conn_log_level warn;
建议保持默认的warn级别,避免info级别产生过多日志影响性能。
实际场景配置示例
场景一:普通网站防护
http {
limit_conn_zone zone=perip:10m;
server {
# 每个IP最多30个并发连接
limit_conn perip 30;
}
}
普通网站30个并发连接足够一个正常用户浏览,同时能挡住低强度CC攻击。
场景二:API接口严格限制
http {
limit_conn_zone zone=api:5m;
server {
location /api/ {
# API接口每个IP最多5个并发
limit_conn api 5;
}
}
}
API接口通常不需要太多并发,5个连接够用,也能有效防止接口被恶意刷调用。
场景三:基于server_name限制
http {
# 按虚拟主机名限制,防止单个站点占用过多连接
limit_conn_zone zone=perserver:10m;
server {
# 每个server_name最多100个并发连接
limit_conn perserver 100;
}
}
适合多站点共享一台服务器的场景,防止单个站点占用过多的服务器资源。
常见问题与排查
1. 限制不生效
检查limit_conn_zone是否放在http块内,limit_conn是否放在正确的server/location中。还要确认变量在当前场景下可用(如果前面有代理,可能需要改用)。
2. 使用CDN后限制异常
CDN场景下所有请求来自CDN的IP,直接限制会误伤。需要在CDN配置中传递真实IP(如X-Forwarded-For),然后:
# 使用realip模块获取真实IP
set_real_ip_from 103.21.244.0/22; # CDN IP段
real_ip_header X-Forwarded-For;
limit_conn_zone zone=perip:10m;
3. 共享内存不够用
如果出现limit_conn_zone内存不足的警告,增大共享内存区大小。估算方法:每个记录占32字节(64位系统),10m约可存储16万条记录。如果网站同时在线IP超过这个数,调大到20m或更多。
配置最佳实践
- 先用
limit_conn设置一个较宽松的值(如50),观察日志,再逐步收紧 - 结合
limit_req一起用,连接数和请求速率双重防护 - 生产环境务必配置
limit_conn_status和自定义错误页面 - CDN/反向代理场景配合
ngx_http_realip_module获取真实IP - 共享内存区大小根据并发量合理设置,宁可稍大也不要太小
- 定期检查error日志中被限制的记录,调整阈值
相关文章
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论