将 limit_conn_log_level 设为 error 可避免高频连接拒绝日志刷屏,防止日志服务因磁盘 I/O 暴涨而瘫痪;它仅控制“拒绝”是否记日志及级别,不改变限流逻辑,真正异常(如 zone 初始化失败)仍会记录。

直接把 limit_conn_log_level 设为 error,就能大幅减少日志刷屏,避免日志服务被自身限流行为拖垮。
为什么默认 warn 会压垮日志服务
当遭遇扫描或轻量 DDoS 时,单个 IP 每秒可能触发几十甚至上千次连接拒绝。Nginx 默认用 warn 级别记录每一次拒绝,error.log 在几秒内就写满百MB,磁盘 I/O 暴涨、日志轮转卡顿、监控采集延迟甚至失败——这本质上是“防御动作反成故障源”。
- 每条日志包含时间戳、客户端 IP、server name、zone 名称等字段,高频写入开销大
- 日志系统(如 rsyslog、journalctl)在高吞吐下容易积压或丢日志
- 真正需要关注的初始化失败、共享内存损坏等 error 级异常,反而被淹没
limit_conn_log_level 的真实作用边界
它只控制“连接被拒”这件事是否落日志、以什么级别落,不改变限流逻辑本身。设成 error 后,正常限流完全不记日志;只有 zone 初始化失败、内存分配异常等极少数底层错误才会触发记录。
-
notice或info和warn实际效果一样:仍每拒一次就写一条,只是日志标记不同 -
crit/alert/emerg在此场景无意义,Nginx 不会在限流时用这些级别 - 想实现“每分钟最多报 5 条”,靠这个指令做不到,必须配合外部聚合(如 Prometheus + nginxlog exporter)
必须搭配 limit_req 才能治本
光调日志级别是“掩耳盗铃”。真正降低拒绝频次,得让请求少被直接干掉:
- 用
limit_req做漏桶缓冲:例如rate=10r/s burst=30 nodelay,允许短时突发,把硬拒绝转为排队或可控延迟 - 把
limit_conn放在更粗粒度维度上:比如按$server_name或$geoip_country_code限流,而不是每个 IP 单独硬卡 - 配合
limit_req_log_level warn:请求级限流本身可留 warn 日志,因它触发频率远低于连接级,不易刷屏
推荐最小可用配置
在 http 块中统一设置:
limit_conn_zone $binary_remote_addr zone=perip:10m; limit_conn perip 100; limit_conn_log_level error; limit_req_zone $binary_remote_addr zone=perip_req:10m rate=20r/s; limit_req zone=perip_req burst=40 nodelay; limit_req_log_level warn;
这样连接数守住底线,请求流有弹性缓冲,error.log 干净,监控可盯 limit_req_status 指标做趋势告警。










