该文章的产生,是因为一次200响应空的故障。当时猜测是tcp队列溢出,但是最后定位到,是登录拦截器HandlerInterceptor的错误逻辑return false,因为错误的return false,导致了空白的200的响应。不过该文章对系统的优化还是有一定的学习意义,故保留。一般情况下,无需过度优化。
运行命令,查看是否有连接队列溢出
netstat -s | grep -i "listen\|overflow\|drop"
将输出以下类似信息(然后将显示的信息,给AI分析)
17 dropped because of missing route
1532 times the listen queue of a socket overflowed
1532 SYNs to LISTEN sockets dropped
TCPBacklogDrop: 176
为什么会出现这个现象?
当客户端(这里是 Nginx)发起连接时:
TCP 三次握手开始。
内核将连接放入 SYN queue(半连接队列)。
握手完成,进入 accept queue(全连接队列)。
应用程序调用 accept() 从队列中取出连接。
如果:
应用处理太慢
并发连接突增
队列长度设置过小
→ accept queue 被填满 → 新连接被丢弃 → SYNs dropped → 客户端收到 Connection refused
解决方案
1. 调大系统级最大队列长度(somaxconn)
当前系统的 somaxconn 可能太小(默认通常是 128 或 511)。
# 查看当前值
cat /proc/sys/net/core/somaxconn
如果小于 1024,建议调大:
# 临时生效(建议直接写入配置文件)
sysctl -w net.core.somaxconn=4096
# 永久生效:写入配置文件
echo 'net.core.somaxconn=4096' | tee -a /etc/sysctl.conf
# 刷新载入配置信息(从配置文件中加载内核参数设置)
sysctl -p
# 查看当前值
cat /proc/sys/net/core/somaxconn
如果小于 1024,建议调大:
# 永久生效:写入配置文件
echo 'net.core.somaxconn=4096' | tee -a /etc/sysctl.conf
# 刷新载入配置信息(从配置文件中加载内核参数设置)
sysctl -p
# 可考虑同时修改Nginx的backlog大小,其默认为511(每个端口可以单独配置,每个端口的backlog之和,不要超过somaxconn)
server {
listen 5173 ssl backlog=1024;# backlog用于控制TCP连接队列的大小
server_name xxxx.com;
ssl_certificate /path/to/your/certificate.crt;
ssl_certificate_key /path/to/your/private.key;
# ... 其他配置(如 location 等)
}
2. 优化后端服务性能(治本)
队列溢出的根本原因是处理速度跟不上请求速度。
建议:
优化接口性能(加缓存、优化逻辑减少数据库查询、增加数据库连接池的连接数)。
使用异步处理,避免阻塞主线程。
3. 配置 Nginx 使用 keepalive 连接池(减少连接创建)
避免 Nginx 每次都新建连接,减少对后端的连接冲击。
注意 keepalive、proxy_http_version、proxy_set_header需同时正确配置,才会生效。
http {
upstream backend {
server 127.0.0.1:8080;
keepalive 32; # 保持32个空闲连接
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1; # 启用 HTTP/1.1,支持持久连接(HTTP/1.1 默认 keep-alive)
proxy_set_header Connection ""; # 清除 Connection 头,防止 Nginx 发送 Connection: close
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}