可实现被限流时记日志:需配合limit_conn_zone、limit_conn、map和log_format,通过识别503状态记录limit_conn标识。

使用 limit_conn_zone 可以限制单个 IP 地址的并发连接数,但它本身不直接记录日志;需配合 limit_conn 和自定义日志条件(如 log_format + map)实现“被限流时记日志”的效果。
配置 limit_conn_zone 限制单 IP 连接
在 http 块中定义共享内存区域,基于客户端 IP 哈希建立连接计数:
limit_conn_zone $binary_remote_addr zone=perip:10m;
说明:
-
$binary_remote_addr比$remote_addr更节省内存(固定 4 字节或 16 字节),推荐用于 IPv4/IPv6 兼容场景 -
zone=perip:10m表示分配 10MB 内存存储连接状态,约可容纳 16 万 IP 条目 - 该指令仅声明“计量方式”,不生效,需在 server 或 location 中调用
limit_conn
在 location 中启用限流并设置阈值
例如限制每个 IP 最多 5 个并发连接:
location /api/ {
limit_conn perip 5;
proxy_pass http://backend;
}
注意:
- 超过阈值的请求会立即返回
503 Service Temporarily Unavailable -
limit_conn对 TCP 连接计数(非请求数),适合防连接耗尽类攻击 - 若同时用了
limit_req(限请求速率),两者独立生效,可叠加防护
记录被限流的 IP 和时间(关键技巧)
limit_conn 本身不触发日志,但可通过 map 捕获状态,再用 log_format 输出:
# 在 http 块中定义 map 变量
map $status $limit_status {
~^503 "limit_conn";
default "";
}
<p>log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" $limit_status';</p><p>access_log /var/log/nginx/access.log main;</p>这样当返回 503 时,日志末尾会追加 limit_conn 标识,便于后续筛选分析。
进阶建议:
- 搭配
fail2ban扫描含limit_conn的日志行,自动封禁高频触发者 - 若需更细粒度(如只记录限流不记录正常请求),可用
access_log ... if=$limit_status;实现条件日志 - 注意:Nginx 1.7.0+ 支持
if参数,旧版本需用map+ 空日志文件 +split_log曲线实现
验证与调试方法
快速确认配置是否生效:
- 执行
nginx -t检查语法,再nginx -s reload生效 - 用
ab -n 100 -c 10 http://your-domain/api/test模拟并发,观察 access.log 中是否出现503和limit_conn - 查看共享内存使用情况:
nginx -T 2>/dev/null | grep limit_conn_zone,或通过 stub_status 模块(需编译支持)监控











