# Nginx Buffer 和 Cache 配置完全汇总
## 一、Buffer 配置详解
### 1. **请求 Buffer(客户端 → Nginx)**
```nginx
# 缓存的内容:HTTP请求的请求体和请求头
client_body_buffer_size 16k; # 缓存客户端请求体(POST/PUT等的数据)
client_header_buffer_size 1k; # 缓存客户端请求头(GET/POST/PUT等所有请求)
client_max_body_size 10m; # 允许的最大请求体大小
client_body_temp_path /tmp/nginx_body; # 请求体临时文件路径
client_body_in_file_only off; # 是否总是将请求体写入文件
client_body_timeout 60s; # 读取请求体超时时间
```
**缓存的内容**:
- `client_body_buffer_size` → **POST/PUT的请求体数据**(表单、JSON、上传文件等)
- `client_header_buffer_size` → **所有请求的HTTP头部**(GET/POST/PUT/HEAD等)
### 2. **代理 Buffer(Nginx → 后端)**
```nginx
# 缓存的内容:后端服务器的响应数据
proxy_buffering on|off; # 是否启用代理缓冲(默认on)⚠️ 缓冲的是后端响应
proxy_buffer_size 4k; # 单个缓冲区大小(响应头缓冲区)
proxy_buffers 8 4k; # 缓冲区数量和大小(响应体缓冲区)
proxy_busy_buffers_size 8k; # 忙碌时缓冲区大小
proxy_temp_file_write_size 16k; # 临时文件写入大小
proxy_temp_path /tmp/nginx_proxy; # 临时文件路径
```
**`proxy_buffering on` 缓冲的内容**:
- **后端服务器的完整HTTP响应**(响应头 + 响应体)
- **GET/POST/PUT/DELETE等所有请求的响应**
- 包含状态码、响应头、响应体所有数据
### 3. **FastCGI Buffer**
```nginx
# 缓存的内容:FastCGI进程的响应数据
fastcgi_buffering on|off; # 是否启用FastCGI缓冲
fastcgi_buffer_size 4k; # 响应头缓冲区
fastcgi_buffers 8 4k; # 响应体缓冲区
fastcgi_busy_buffers_size 8k; # 忙碌缓冲区
fastcgi_temp_path /tmp/nginx_fastcgi; # 临时文件路径
```
### 4. **输出 Buffer(Nginx → 客户端)**
```nginx
# 缓存的内容:发送给客户端的响应数据
output_buffers 1 512k; # 输出缓冲区(每个连接)
postpone_output 1460; # 推迟输出阈值(字节)
sendfile_max_chunk 512k; # sendfile每次调用限制
```
## 二、Cache 配置详解
### 1. **代理缓存(Proxy Cache)**
```nginx
# 缓存的内容:后端服务器的完整响应
proxy_cache_path /var/cache/nginx
levels=1:2 # 目录层级
keys_zone=my_cache:10m # 内存元数据区(缓存键信息)
max_size=1g # 磁盘缓存最大大小
inactive=60m # 60分钟未访问则清理
loader_threshold=300 # 缓存加载参数
loader_files=200; # 每次加载文件数
# 启用缓存
proxy_cache my_cache;
proxy_cache_key "$scheme$request_method$host$request_uri"; # 缓存键
proxy_cache_valid 200 302 10m; # 不同状态码缓存时间
```
**代理缓存存储的内容**:
- **完整的HTTP响应**(状态码、响应头、响应体)
- **GET请求的响应**(主要缓存GET,但也可配置缓存POST响应)
- 可配置按`$request_method`区分缓存键
### 2. **FastCGI 缓存**
```nginx
# 缓存的内容:FastCGI进程的动态响应
fastcgi_cache_path /var/cache/nginx/fastcgi
levels=1:2
keys_zone=fcgi_cache:10m
max_size=1g
inactive=60m;
fastcgi_cache fcgi_cache;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
```
## 三、如何彻底关闭 Buffer
### 1. **完全关闭客户端请求缓冲**
```nginx
# 极端配置:最小化请求缓冲
client_body_buffer_size 0; # ❌ 完全不缓冲请求体(危险)
client_header_buffer_size 1; # 最小化请求头缓冲
client_body_in_single_buffer off; # 不合并缓冲区
client_body_in_file_only on; # 请求体直接写文件(不缓冲)
```
### 2. **完全关闭代理缓冲**
```nginx
# 彻底禁用代理缓冲
proxy_buffering off; # ✅ 关闭代理缓冲(响应立即转发)
proxy_request_buffering off; # ✅ 关闭请求体缓冲(请求立即转发)
proxy_buffer_size 4k; # 仍需最小缓冲区用于响应头
proxy_buffers 1 4k; # 最小缓冲区数量
proxy_busy_buffers_size 4k;
proxy_max_temp_file_size 0; # ❌ 禁止使用临时文件(可能导致内存溢出)
# 流式传输必须的
chunked_transfer_encoding on; # 启用分块传输编码
tcp_nodelay on; # 禁用Nagle算法
```
### 3. **完全关闭输出缓冲**
```nginx
# 关闭发送给客户端的缓冲
output_buffering off; # ❌ 完全关闭输出缓冲
postpone_output 0; # 立即发送任何数据
sendfile off; # 禁用sendfile(不使用零拷贝)
# 或最小化配置
output_buffers 1 4k; # 最小输出缓冲区
```
## 四、如何彻底关闭 Cache
### 1. **完全禁用代理缓存**
```nginx
# 方法1:全局禁用
proxy_cache off; # ✅ 关闭代理缓存
proxy_no_cache 1; # ✅ 从不缓存
proxy_cache_bypass 1; # ✅ 总是绕过缓存
# 方法2:设置极短缓存时间
proxy_cache_valid 1s; # 1秒后过期(相当于不缓存)
proxy_cache_min_uses 1000000; # 极大使用次数阈值
# 方法3:禁用缓存键
proxy_cache_key ""; # 空缓存键(无法匹配)
```
### 2. **完全禁用 FastCGI 缓存**
```nginx
fastcgi_cache off;
fastcgi_no_cache 1;
fastcgi_cache_bypass 1;
```
### 3. **清理缓存目录**
```bash
# 停止Nginx
nginx -s stop
# 删除所有缓存文件
rm -rf /var/cache/nginx/*
# 删除临时文件
rm -rf /tmp/nginx_* /var/lib/nginx/tmp/*
# 重启Nginx
nginx
```
## 五、Buffer 和请求方法的关系
### 1. **Buffer 对不同请求方法的影响**
```nginx
# Buffer 对请求方法的处理:
# 1. GET/HEAD/DELETE → 通常无请求体,只有请求头缓冲
# 2. POST/PUT/PATCH → 既有请求头缓冲,也有请求体缓冲
# 配置示例:针对不同方法优化
map $request_method $buffer_policy {
default "on"; # 默认开启缓冲
"GET" "off"; # GET请求关闭缓冲(实时性要求高)
"POST" "on"; # POST请求开启缓冲(数据完整性重要)
"PUT" "on"; # PUT请求开启缓冲
}
location /api/ {
proxy_buffering $buffer_policy;
proxy_pass http://backend;
}
```
### 2. **Cache 对不同请求方法的处理**
```nginx
# 默认代理缓存通常只缓存GET请求
# 但可以配置缓存其他方法
# 只缓存GET请求(默认行为)
proxy_cache_methods GET; # ✅ 只缓存GET请求
# 缓存GET和HEAD
proxy_cache_methods GET HEAD;
# 缓存所有请求方法(谨慎!)
proxy_cache_methods GET HEAD POST;
# 缓存键中区分请求方法
proxy_cache_key "$request_method$host$request_uri";
```
## 六、完整关闭配置示例
### 1. **实时流媒体服务器配置(完全关闭Buffer)**
```nginx
location /live/ {
proxy_pass http://stream_backend;
# 彻底关闭所有缓冲
proxy_buffering off; # 关闭响应缓冲
proxy_request_buffering off; # 关闭请求缓冲
proxy_buffer_size 4k; # 最小响应头缓冲区
proxy_buffers 1 4k; # 最小缓冲区
# 关闭输出缓冲
output_buffers 1 4k;
postpone_output 0;
# 关闭所有缓存
proxy_cache off;
proxy_no_cache 1;
proxy_cache_bypass 1;
# 流式传输优化
chunked_transfer_encoding on;
tcp_nodelay on;
tcp_nopush off;
# 长连接设置
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
# 禁用临时文件
proxy_max_temp_file_size 0;
}
```
### 2. **高性能API网关配置(选择性关闭Buffer)**
```nginx
# 根据请求方法动态调整
map $request_method $should_buffer {
"GET" "off"; # GET:低延迟优先
"POST" "on"; # POST:完整性优先
"PUT" "on"; # PUT:完整性优先
default "off"; # 其他:低延迟优先
}
server {
location /api/ {
proxy_pass http://api_backend;
# 动态缓冲控制
proxy_buffering $should_buffer;
proxy_request_buffering $should_buffer;
# 关闭缓存(API需要实时数据)
proxy_cache off;
# 最小化缓冲区
proxy_buffer_size 4k;
proxy_buffers 4 4k;
# 快速失败
proxy_connect_timeout 3s;
proxy_send_timeout 10s;
proxy_read_timeout 30s;
}
}
```
### 3. **完全禁用所有Buffer和Cache的极端配置**
```nginx
http {
# 全局关闭所有可能的缓冲
client_body_buffer_size 0;
client_header_buffer_size 1;
client_body_in_file_only on;
# 全局关闭代理缓冲
proxy_buffering off;
proxy_request_buffering off;
proxy_buffer_size 1;
proxy_buffers 1 1;
proxy_busy_buffers_size 1;
# 全局关闭输出缓冲
output_buffers 1 1;
postpone_output 0;
sendfile off;
# 全局关闭所有缓存
proxy_cache off;
fastcgi_cache off;
uwsgi_cache off;
scgi_cache off;
# 禁用临时文件
proxy_max_temp_file_size 0;
client_body_temp_path /dev/null; # 丢弃临时文件
proxy_temp_path /dev/null;
fastcgi_temp_path /dev/null;
}
```
## 七、重要注意事项
### 1. **关闭Buffer的风险**
```nginx
# 危险:完全关闭可能导致的问题
# 1. 内存溢出(大量并发连接)
# 2. 后端服务器被慢客户端阻塞
# 3. 网络效率降低(小数据包过多)
# 4. 文件上传失败(client_body_buffer_size=0)
# 安全的最小配置
client_body_buffer_size 8k; # 至少8KB用于请求体
proxy_buffer_size 4k; # 至少4KB用于响应头
```
### 2. **Buffer和Cache的关系**
```
数据流向:客户端 → [请求Buffer] → Nginx → [代理Buffer] → 后端
↓
[代理Cache] ← 存储响应
↓
客户端 ← [输出Buffer] ← Nginx
# Buffer是临时的,Cache是持久的
# Buffer影响延迟,Cache影响重复请求的速度
```
### 3. **监控Buffer使用情况**
```bash
# 监控Buffer状态
watch -n 1 '
echo "=== Nginx Buffer 状态 ==="
echo "内存使用:"
ps aux | grep nginx | grep -v grep | awk "{print \$6/1024\" MB\"}"
echo ""
echo "临时文件:"
find /tmp /var/lib/nginx -name "*tmp*" -type f 2>/dev/null | wc -l
echo ""
echo "活跃连接:"
ss -tn sport = :80 | grep -c ESTAB
'
```
## 八、总结表格
| 配置项 | 缓冲的内容 | 影响范围 | 完全关闭命令 |
|--------|-----------|----------|--------------|
| `client_body_buffer_size` | **POST/PUT请求体** | 请求体数据 | `client_body_buffer_size 0` |
| `client_header_buffer_size` | **所有请求头** | HTTP头部 | `client_header_buffer_size 1` |
| `proxy_buffering` | **后端响应**(头+体) | 代理响应 | `proxy_buffering off` |
| `proxy_request_buffering` | **转发给后端的请求体** | 代理请求 | `proxy_request_buffering off` |
| `output_buffers` | **发送给客户端的响应** | 输出数据 | `output_buffers 1 1` |
| `proxy_cache` | **后端完整响应**(持久化) | 重复请求 | `proxy_cache off` |
**核心要点**:
1. **Buffer缓冲的是传输中的数据**(临时存储)
2. **Cache缓存的是完整的响应**(持久存储)
3. **不同请求方法受Buffer影响不同**(GET无请求体,POST有请求体)
4. **彻底关闭Buffer可能带来性能问题**,需谨慎评估
# 如何判断 output_buffers 是否阻塞
## 一、output_buffers 阻塞的判定方法
### 1. **直接监控指标**
```bash
# 方法1:查看Nginx活跃连接状态
ss -tnp | grep nginx | awk '
/ESTAB/ {
if ($2 > 0 || $3 > 0) {
print "可能存在阻塞: Local->" $4, "Peer->" $5, "Send-Q:" $2, "Recv-Q:" $3
}
}'
# 关键字段解释:
# Send-Q > 0: 发送队列有数据积压(output_buffers可能阻塞)
# Recv-Q > 0: 接收队列有数据积压
```
### 2. **使用 Nginx 状态模块**
```nginx
# 启用 stub_status 模块
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
```
```bash
# 查看状态
curl http://127.0.0.1/nginx_status
# 输出示例:
Active connections: 291
server accepts handled requests
16630948 16630948 31070465
Reading: 6 Writing: 179 Waiting: 106
# 判断标准:
# Writing 数值持续很高 → output_buffers可能有阻塞
# 正常情况下 Writing 应该很小(< 10%的总连接数)
```
### 3. **实时监控脚本**
```bash
#!/bin/bash
# monitor_output_buffer.sh
while true; do
clear
echo "=== Output Buffers 阻塞监控 ==="
echo ""
# 1. 查看Writing状态
echo "1. Nginx Writing状态:"
curl -s http://127.0.0.1/nginx_status 2>/dev/null | grep -A1 "Reading:" | \
awk '{print " Reading:" $2, "Writing:" $4, "Waiting:" $6}'
# 2. 查看TCP发送队列
echo -e "\n2. TCP发送队列统计:"
ss -tn sport = :80 or sport = :443 | awk '
/ESTAB/ {
total++
if ($2 > 0) blocked++
sum_sendq += $2
}
END {
printf " 总连接: %d\n", total
printf " 阻塞连接: %d (%.1f%%)\n", blocked, (blocked/total)*100
printf " 平均Send-Q: %.1f bytes\n", sum_sendq/total
}'
# 3. 查看内存使用
echo -e "\n3. Nginx进程内存:"
ps aux | grep "nginx: worker" | grep -v grep | head -3 | \
awk '{printf " PID:%s RSS:%s MB VSZ:%s MB\n", $2, $6/1024, $5/1024}'
# 4. 查看磁盘临时文件(output_buffers溢出时)
echo -e "\n4. 临时文件检查:"
find /tmp /var/lib/nginx -name "*tmp*" -type f 2>/dev/null | \
wc -l | awk '{print " 临时文件数:", $1}'
sleep 2
done
```
## 二、专业诊断工具
### 1. **使用 strace 跟踪系统调用**
```bash
# 跟踪Nginx的write系统调用
strace -p $(pgrep nginx | head -1) -e trace=write -s 100 2>&1 | \
head -20
# 如果看到大量 EAGAIN/EWOULDBLOCK 错误,说明output_buffers阻塞
# 正常情况:write()立即返回写入字节数
# 阻塞情况:write()阻塞或返回EAGAIN
```
### 2. **使用 gdb 调试**
```bash
# 安装debug符号
apt-get install nginx-dbg
# 附加到Nginx进程
gdb -p $(pgrep nginx | head -1)
# 在gdb中检查缓冲区
(gdb) call ngx_cycle->connections
(gdb) call ngx_cycle->write_events
```
### 3. **使用 SystemTap 分析**
```bash
# SystemTap脚本检查output_buffers
cat > output_buffer_monitor.stp << 'EOF'
probe process("nginx").function("ngx_http_write_filter") {
printf("PID: %d, Connection: %p, Buffer: %d bytes\n",
pid(), $r->connection, $in->buf->last - $in->buf->pos)
}
probe process("nginx").function("ngx_http_output_filter") {
printf("Output filter called: chain length = %d\n", $in? @cast($in, "ngx_chain_t")->nelts : 0)
}
EOF
stap output_buffer_monitor.stp
```
## 三、日志分析诊断
### 1. **启用详细日志**
```nginx
# 自定义日志格式包含buffer信息
log_format buffer_debug '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'bytes_sent=$bytes_sent '
'request_time=$request_time '
'upstream_response_time=$upstream_response_time '
'sent_http_content_length=$sent_http_content_length '
'connection_requests=$connection_requests '
'pipe=$pipe '
'gzip_ratio=$gzip_ratio';
server {
access_log /var/log/nginx/buffer_debug.log buffer_debug;
# 添加调试响应头
add_header X-Buffer-Debug "bytes_sent=$bytes_sent" always;
}
```
### 2. **分析日志判断阻塞**
```bash
# 分析output_buffers阻塞模式
awk '
# 提取关键字段
{
for(i=1; i<=NF; i++) {
if($i ~ /bytes_sent=/) split($i, a, "=")
if($i ~ /request_time=/) split($i, b, "=")
}
# 判断逻辑:发送字节少但时间长 → 可能阻塞
if (a[2] < 1000 && b[2] > 1.0) {
print "可能阻塞: 发送" a[2] "字节耗时" b[2] "秒 - " $0
}
}
' /var/log/nginx/buffer_debug.log | head -20
```
## 四、实际场景诊断
### 场景1:output_buffers 过小导致阻塞
```nginx
# 问题配置
output_buffers 1 4k; # 太小!
postpone_output 1460;
# 症状:
# 1. 小文件响应慢
# 2. Writing连接数高
# 3. TCP Send-Q积压
```
**诊断命令**:
```bash
# 监控单个连接的缓冲区状态
watch -n 0.5 '
echo "=== 实时连接状态 ==="
ss -tin sport = :80 | grep -v "^State" | head -5 | \
awk "{print \"连接:\" \$5, \"Send-Q:\" \$2, \"状态:\" \$0}" | grep -i "applimited\|send"
'
```
### 场景2:网络拥塞导致 output_buffers 阻塞
```bash
# 诊断网络状况
# 1. 查看网络丢包
netstat -s | grep -E "segments retransmited|packet receive errors"
# 2. 查看带宽使用
iftop -i eth0 -P
# 3. 查看TCP重传
ss -tin sport = :80 | grep -c "retrans"
```
### 场景3:客户端接收慢导致阻塞
```bash
# 诊断客户端问题
# 1. 查看各连接的发送速率
ss -tin sport = :80 | awk '/send/ {print $0}'
# 2. 识别慢客户端
ss -tinp sport = :80 | awk '
/send/ {
for(i=1;i<=NF;i++)
if($i ~ /send/) print $5, $(i+1)
}' | sort -k2 -n | head -10
```
## 五、性能测试模拟
### 1. **模拟output_buffers阻塞测试**
```bash
# 创建慢速客户端模拟工具
cat > slow_client.py << 'EOF'
import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 80))
s.send(b'GET /large-file.txt HTTP/1.1\r\nHost: localhost\r\n\r\n')
# 故意慢速接收
while True:
data = s.recv(10) # 每次只收10字节
if not data:
break
time.sleep(0.1) # 延迟0.1秒
print(f"收到 {len(data)} 字节")
EOF
# 运行多个慢客户端
for i in {1..10}; do
python3 slow_client.py &
done
```
### 2. **监控阻塞效果**
```bash
# 运行测试时监控
watch -n 1 '
echo "=== 阻塞测试监控 ==="
echo "Writing连接数:"
curl -s http://127.0.0.1/nginx_status 2>/dev/null | grep -o "Writing: [0-9]*"
echo ""
echo "TCP发送队列:"
ss -tn sport = :80 | awk \"/ESTAB/ {sum+=\$2} END {print \\\"总Send-Q: \\\" sum}\"
'
```
## 六、优化和解决
### 1. **调整 output_buffers 配置**
```nginx
# 优化配置示例
http {
# 增大output_buffers
output_buffers 4 32k; # 4个32KB缓冲区(共128KB)
postpone_output 0; # 立即发送,不等待
# 调整TCP参数
tcp_nodelay on; # 禁用Nagle算法
tcp_nopush off; # 禁用数据包合并
# 调整系统级限制
sendfile_max_chunk 512k; # 限制每次sendfile大小
}
```
### 2. **针对不同场景优化**
```nginx
# 场景1:API服务(需要低延迟)
location /api/ {
output_buffers 1 8k; # 小缓冲区
postpone_output 0; # 立即发送
tcp_nodelay on;
}
# 场景2:文件下载(需要高吞吐)
location /download/ {
output_buffers 4 64k; # 大缓冲区
postpone_output 1460; # 优化TCP数据包
sendfile on;
sendfile_max_chunk 1m;
}
# 场景3:流媒体(需要连续流)
location /stream/ {
output_buffers 2 16k; # 中等缓冲区
postpone_output 0;
tcp_nodelay on;
chunked_transfer_encoding on;
}
```
### 3. **系统级优化**
```bash
# 调整系统TCP缓冲区
sysctl -w net.ipv4.tcp_wmem="4096 16384 4194304"
sysctl -w net.core.wmem_max=4194304
sysctl -w net.ipv4.tcp_notsent_lowat=16384
# 调整文件描述符限制
ulimit -n 65535
echo "nginx soft nofile 65535" >> /etc/security/limits.conf
```
## 七、自动化诊断脚本
### 完整诊断工具
```bash
#!/bin/bash
# diagnose_output_buffer.sh
echo "=== Nginx output_buffers 完整诊断报告 ==="
echo "生成时间: $(date)"
echo ""
# 1. 检查配置
echo "1. 检查Nginx配置:"
nginx -T 2>/dev/null | grep -E "output_buffers|postpone_output|tcp_nodelay|sendfile" | \
while read line; do
echo " $line"
done
# 2. 检查当前状态
echo -e "\n2. 当前连接状态:"
STATUS=$(curl -s http://127.0.0.1/nginx_status 2>/dev/null)
if [ $? -eq 0 ]; then
echo "$STATUS" | while read line; do
echo " $line"
done
else
echo " Nginx状态接口不可用"
fi
# 3. 检查TCP队列
echo -e "\n3. TCP发送队列分析:"
ss -tn sport = :80 or sport = :443 2>/dev/null | awk '
BEGIN {total=0; blocked=0; max_sendq=0}
/ESTAB/ {
total++
if ($2 > 0) {
blocked++
if ($2 > max_sendq) max_sendq = $2
}
}
END {
printf " 总连接数: %d\n", total
printf " 阻塞连接数: %d (%.1f%%)\n", blocked, (blocked/total)*100
printf " 最大Send-Q: %d bytes\n", max_sendq
if (blocked/total > 0.3) {
printf " ⚠️ 警告: 超过30%%连接存在阻塞\n"
}
}'
# 4. 检查内存和临时文件
echo -e "\n4. 资源使用情况:"
echo " 内存使用:"
ps aux | grep "nginx: worker" | grep -v grep | head -2 | \
awk '{printf " PID:%s RSS:%.1fMB VSZ:%.1fMB\n", $2, $6/1024, $5/1024}'
echo " 临时文件:"
TMP_FILES=$(find /tmp /var/lib/nginx -name "*tmp*" -type f 2>/dev/null | wc -l)
echo " 数量: $TMP_FILES"
if [ $TMP_FILES -gt 100 ]; then
echo " ⚠️ 警告: 临时文件过多,可能缓冲区不足"
fi
# 5. 建议
echo -e "\n5. 诊断建议:"
echo " - 如果Writing连接数 > 总连接数的10%,考虑增大output_buffers"
echo " - 如果Send-Q持续 > 0,检查网络或客户端接收能力"
echo " - 临时文件过多时,增大内存缓冲区或优化应用"
echo " - 考虑使用tcp_nodelay on和调整postpone_output"
```
## 八、监控告警规则
### Prometheus + Grafana 监控规则
```yaml
# prometheus.rules.yml
groups:
- name: nginx_output_buffer
rules:
- alert: NginxOutputBufferBlocked
expr: |
sum(rate(nginx_http_connections{state="writing"}[5m]))
/ sum(nginx_http_connections{state="waiting"}) > 0.3
for: 2m
labels:
severity: warning
annotations:
summary: "Nginx output buffers 阻塞超过30%"
description: "{{ $labels.instance }} 有 {{ $value }}% 的连接在writing状态"
- alert: NginxHighSendQueue
expr: |
sum(nginx_tcp_send_queue_bytes) > 1048576 # 1MB
for: 1m
labels:
severity: critical
annotations:
summary: "Nginx TCP发送队列积压超过1MB"
description: "{{ $labels.instance }} 发送队列积压 {{ $value }} 字节"
```
## 九、总结判断标准
### output_buffers 阻塞的**明确标志**:
1. **核心指标**:
- `Writing` 连接数 > 总连接数的 20%
- TCP `Send-Q` 持续 > 0
- `request_time` 远大于 `upstream_response_time`
2. **系统指标**:
- Nginx 进程 RSS 内存持续增长
- `/tmp` 或 `/var/lib/nginx` 临时文件增多
- 系统 `netstat -s` 显示重传增加
3. **性能表现**:
- 小文件响应变慢
- 下载速度不稳定
- 客户端频繁超时
### 快速检查命令:
```bash
# 一键检查output_buffers阻塞
检查配置:nginx -T 2>/dev/null | grep -A2 -B2 "output_buffers"
检查状态:curl -s http://127.0.0.1/nginx_status | grep -o "Writing: [0-9]*"
检查队列:ss -tn sport = :80 | awk '/ESTAB/ && $2>0 {print $5, $2}' | head -5
检查内存:ps aux | grep "nginx: worker" | head -1 | awk '{print "RSS:" $6/1024"MB"}'
```
## 十、补充说明
### 1. **output_buffers 阻塞的根本原因**
- **客户端接收速度慢**:客户端无法及时处理接收的数据
- **网络拥塞**:网络带宽不足或延迟高
- **缓冲区设置不当**:output_buffers 太小或 postpone_output 设置不合理
- **系统限制**:文件描述符不足或内存限制
### 2. **output_buffers 与其他 Buffer 的关系**
```
output_buffers 是数据流的最后一环:
客户端请求 → client_body_buffer → 处理 → proxy_buffer → 后端响应 →
proxy_buffer → 处理 → output_buffers → 客户端
如果 output_buffers 阻塞,会影响整个链路的吞吐量
```
### 3. **实际生产建议**
```nginx
# 生产环境推荐配置
http {
# 根据业务类型调整
output_buffers 2 32k; # 通用场景:2个32KB缓冲区
postpone_output 0; # 实时应用立即发送
tcp_nodelay on; # 禁用Nagle算法
# 监控关键指标
log_format detailed '$remote_addr - [$time_local] "$request" '
'$status $body_bytes_sent $request_time '
'$bytes_sent $upstream_response_time';
# 定期检查和优化
# 1. 监控 /nginx_status 的 Writing 连接数
# 2. 检查 ss -tin 的 Send-Q 值
# 3. 分析 access_log 中的 $request_time 和 $bytes_sent
}
```
### 4. **紧急处理方法**
```bash
# 发现阻塞时的紧急处理
# 1. 临时增大缓冲区
nginx -T 2>/dev/null | grep "output_buffers"
# 如果太小,临时修改为:output_buffers 4 64k;
# 2. 重启受影响的worker进程
kill -HUP $(pgrep nginx)
# 3. 识别并断开慢客户端
ss -tinp sport = :80 | awk '/ESTAB/ && $2>10000 {print $7}' | \
cut -d= -f2 | xargs kill -9
# 4. 紧急关闭输出缓冲(牺牲性能换取可用性)
# 临时修改配置:output_buffers 1 4k; postpone_output 0;
```
**记住**:output_buffers 阻塞通常是系统问题的**表现**而不是**原因**。需要从客户端、网络、配置等多个维度综合分析解决。