hyperf服务未监听nginx请求,需依次检查:端口是否listen、swoole进程是否运行、server.port是否为整数、docker端口映射与proxy_pass地址是否匹配、防火墙/selinux是否拦截、worker_num与keepalive是否适配,并用tcpdump抓包定位真实瓶颈。

Hyperf服务没监听到Nginx请求,先确认Swoole是否真在跑
502错误第一眼就该怀疑Hyperf根本没接收到请求——不是转发失败,而是压根没人在听。用netstat -tuln | grep :9501(假设你配的是9501)看端口是否处于LISTEN状态。如果没输出,说明Swoole进程根本没起来,或者启动时因配置/权限/端口占用失败静默退出了。
常见漏点:
-
php bin/hyperf.php start启动后没加&或nohup,终端关闭就挂了 -
server.port在config/autoload/server.php里被写成字符串"9501"而非整数9501,Swoole会静默忽略 - 用了
docker run但没暴露端口,或宿主机防火墙拦了容器端口映射
Nginx proxy_pass 地址必须和Hyperf实际监听地址严格一致
Hyperf默认监听127.0.0.1:9501,不是0.0.0.0:9501;如果你的Nginx在宿主机,而Hyperf在Docker容器里,proxy_pass http://127.0.0.1:9501 就会连错——它连的是宿主机本机,不是容器。
正确做法取决于部署结构:
- Hyperf与Nginx同机:用
proxy_pass http://127.0.0.1:9501,确保Hyperf的server.host设为'127.0.0.1' - Hyperf在Docker,Nginx在宿主机:改用容器名或
host.docker.internal(Mac/Win),如proxy_pass http://hyperf-app:9501;Linux需手动配置--add-host=host.docker.internal:host-gateway - Hyperf监听
0.0.0.0:9501且允许外部访问:仅限内网可信环境,同时确认server.host设为'0.0.0.0'
防火墙或SELinux可能直接丢掉连接包
即使端口监听了、Nginx地址也对,Linux防火墙也可能在SYN阶段就把包干掉了。先快速验证:curl -v http://127.0.0.1:9501 在Nginx所在机器本地执行。如果返回Connection refused,是Hyperf问题;如果卡住或超时,大概率是防火墙挡路。
检查和放行:
- CentOS 7+/RHEL:运行
sudo firewall-cmd --list-ports,缺9501就加sudo firewall-cmd --add-port=9501/tcp --permanent && sudo firewall-cmd --reload - Ubuntu/Debian:
sudo ufw status看是否启用,启用则执行sudo ufw allow 9501 - SELinux(少见但致命):
sudo setsebool -P httpd_can_network_connect 1,否则Nginx worker进程无权向外发起TCP连接
别忽略Hyperf的worker_num和Nginx的keepalive不匹配
Hyperf默认worker_num = 4,而Nginx upstream默认长连接池大小是keepalive 32。当并发突增,Nginx可能复用一个已断开的连接发请求,Hyperf侧已关闭该fd,直接RST,Nginx记一条upstream prematurely closed connection然后回502。
稳妥做法:
- 在Nginx upstream块中显式限制连接复用数:
keepalive 4;(不超过Hyperf worker数) - 或在Hyperf配置里加大
worker_num,并同步调高max_connections(避免accept队列溢出) - 加一条保底:
proxy_next_upstream error timeout http_502;,让Nginx自动切下一台(单实例也建议加,防偶发抖动)
真正难缠的502往往卡在“看起来都对”的环节:端口开着、地址能ping通、日志没报错——这时候得盯住tcpdump抓包看SYN有没有发出、ACK有没有回来、RST是谁发的。Swoole底层不走传统PHP-FPM那套Unix socket路径,很多老经验在这里会失效。











