本质是上游服务未监听对应地址端口,“没人接单”;需依次检查后端是否真实运行并LISTEN、配置与监听地址是否一致、连接数是否耗尽、系统资源(文件描述符/端口)是否受限。

高并发压测中 upstream 报 ConnectionRefused,本质是 Nginx 无法把请求成功转给后端服务(如 PHP-FPM、Tomcat、Node.js 等),不是网络不通,而是“上游没人接单”。错误日志典型形式是:
connect() to unix:/var/run/php-fpm.sock failed (111: Connection refused) while connecting to upstream
或
connect() to 127.0.0.1:8080 failed (111: Connection refused) while connecting to upstream
先确认后端服务是否真在监听
ConnectionRefused 的第一层原因永远是“目标进程没在对应地址+端口上 LISTEN”。别跳过这步:
- 查 Unix socket:用
ls -l /var/run/php-fpm.sock看文件是否存在;再用sudo ss -ltp | grep php确认是否有进程绑定该 socket - 查 TCP 端口:运行
sudo ss -tlnp | grep ':8080'(替换为你的端口),看是否有 PID 和进程名显示。没有输出 = 后端根本没启动,或启动失败静默退出 - 看后端日志:PHP-FPM 查
/var/log/php-fpm/error.log;Tomcat 查catalina.out;留意 “failed to bind”、“address already in use”、“permission denied” 等关键词
检查 upstream 配置与实际运行状态是否一致
Nginx 配置里写的地址,必须和后端真实监听的一致,常见错位点:
- 配置写的是
fastcgi_pass unix:/tmp/php-fpm.sock,但 PHP-FPM 实际监听的是/var/run/php-fpm.sock—— 路径不匹配直接拒连 - 配置写的是
proxy_pass http://127.0.0.1:3000,但 Node.js 应用监听的是0.0.0.0:3000或127.0.0.1:3001—— IP 或端口对不上 - 使用 Docker 时,Nginx 在宿主机,后端在容器内,却仍配
127.0.0.1—— 容器网络隔离下,必须用容器 IP 或 service 名(如backend:3000)
排查后端连接能力是否被耗尽
服务虽在运行,但已无空闲连接槽位,新请求进来就会被内核直接拒绝(errno 111):
- PHP-FPM:检查
pm.max_children是否太小;压测时看pm.status_path输出的active processes是否长期打满;日志中出现reached pm.max_children就是明确信号 - Tomcat:检查
server.xml中maxConnections和acceptCount;压测中用jstat -gc <pid>看是否频繁 GC 导致线程卡死;netstat -an | grep :8080 | grep ESTAB | wc -l看真实连接数是否逼近上限 - 数据库类 upstream(如 MySQL):查
show variables like 'max_connections';和show status like 'Threads_connected';,连接数打满也会让 Nginx 连不上
验证系统级资源限制是否触发拒绝
Linux 内核层面的限制,会让连接在到达后端前就被掐断:
- 文件描述符不足:运行
cat /proc/$(pgrep php-fpm)/limits | grep "Max open files"(替换为对应进程),若 Soft Limit 是 1024,高并发下极易耗尽。需在 systemd service 文件中加LimitNOFILE=65535并重载 - 临时端口耗尽(尤其代理到动态端口时):检查
net.ipv4.ip_local_port_range是否太窄,建议设为1024 65535;同时调大net.ipv4.tcp_tw_reuse = 1 - SELinux 或 AppArmor 强制拦截:临时执行
setenforce 0测试是否缓解;若恢复则需补 SELinux 策略,如setsebool -P httpd_can_network_connect 1


















