在高并发场景下出现连接重置(Connection Reset)问题,通常与资源限制、超时配置、队列溢出或TCP内核参数有关。以下是针对Nginx、Uvicorn和Gunicorn的优化方案:
连接池与缓冲区
worker_processes auto; # 根据CPU核心数自动分配
worker_rlimit_nofile 100000; # 每个worker能打开的文件描述符上限
events {
worker_connections 20480; # 单个worker最大连接数
multi_accept on; # 一次性接受所有新连接
}
http {
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 512k;
}
超时与Keepalive
upstream backend {
server 127.0.0.1:8000;
keepalive 100; # 保持长连接池大小
}
server {
keepalive_timeout 60s; # 客户端长连接保持时间
keepalive_requests 10000; # 单个连接最大请求数
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_read_timeout 300s; # 关键:增加后端响应超时
proxy_send_timeout 300s;
proxy_connect_timeout 75s;
}
}
Worker配置
# 使用Uvicorn Workers(适合异步框架如FastAPI)
gunicorn -w $((2 * $(nproc) + 1)) --worker-class uvicorn.workers.UvicornWorker --timeout 120 app:app
# 同步Worker配置(适合Django等同步框架)
gunicorn -w $((2 * $(nproc) + 1)) --threads 4 --max-requests 1000 --timeout 120 app:app
-w
: Worker数量 = 2*CPU核心 + 1--max-requests
: 防止内存泄漏,定期重启Worker--timeout
: 请求处理超时时间需大于Nginx的proxy_read_timeout
异步处理优化
# 在ASGI应用(如FastAPI)中启用异步路由
@app.get("/io_task")
async def io_bound_task():
await some_async_io()
TCP内核参数
# 调整临时端口范围
echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range
# 加快TIME_WAIT回收
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
# 增加最大文件描述符
ulimit -n 100000
sysctl -w fs.file-max=100000
SYN洪水防护
sysctl -w net.ipv4.tcp_max_syn_backlog=65536
sysctl -w net.core.somaxconn=65536
监控指标
netstat -s | grep -E 'reset|timeout'
:检查RST包数量ss -s
:查看当前连接状态分布/var/log/nginx/error.log
搜索 104: Connection reset by peer
常见原因
proxy_read_timeout
和Gunicorn超时)ip_local_port_range
)使用wrk
或ab
模拟高并发:
wrk -t12 -c4000 -d30s http://your_service
观察是否出现Socket errors: connect 0, read 0, write 0, timeout 0, reset X
通过上述多层级优化,可显著降低高并发下的连接重置问题。建议逐步调整参数并配合监控工具(如Prometheus+Grafana)验证效果。