启动PHP-CLI运行的WebSocket服务器后Nginx+PHP-FPM出现504超时求助
嘿,这个问题我之前帮朋友排查过类似的,启动WebSocket服务器后Nginx的PHP服务报504超时,核心大概率是资源冲突或者PHP进程池不够用的问题,咱们一步步来拆解解决:
你直接用php webSocketServer.php启动WebSocket服务,默认是单进程前台阻塞运行——WebSocket服务本身需要一直监听连接,会持续占用PHP进程资源;如果你的PHP-FPM进程池配置得比较小,或者WebSocket服务的代码有资源泄漏,很容易把系统里的PHP可用资源占满,导致Nginx转发的请求找不到空闲的PHP-FPM进程处理,最终触发504网关超时。
一、先排查基础状态
1. 检查PHP-FPM进程与日志
先确认启动WebSocket后,PHP-FPM是不是真的没空闲进程了:
- 执行命令看PHP-FPM进程状态:
ps aux | grep php-fpm,看看有没有大量进程处于忙碌状态 - 打开PHP-FPM的错误日志(MacOS下用brew装的话,路径一般是
/usr/local/var/log/php-fpm.log),搜一下有没有“max_children reached”或者“timeout”相关的报错——如果有,那就是进程池不够用了。
2. 检查WebSocket进程的资源占用
用top -o cpu命令看系统进程,找到运行WebSocket的php进程,看看它的CPU和内存占用是不是接近100%。如果是的话,说明你的WebSocket代码可能有阻塞逻辑或者内存泄漏,拖垮了系统资源。
二、针对性解决方案
1. 把WebSocket服务后台运行
前台运行的WebSocket服务会占用终端资源,而且意外关闭终端就会导致进程退出,先改成后台启动:
nohup php webSocketServer.php > /dev/null 2>&1 &
这个命令会让WebSocket服务在后台静默运行,不占用当前终端。
2. 调整PHP-FPM进程池配置
打开PHP-FPM的配置文件(路径大概是/usr/local/etc/php/7.2/php-fpm.d/www.conf),修改以下几个关键参数:
pm.max_children:把默认值(一般是10)适当调高,比如改成20,保证有足够的进程处理Nginx的请求,同时给WebSocket留资源pm.start_servers:设置成max_children的1/4左右就行,比如5pm.min_spare_servers和pm.max_spare_servers:分别设为3和8,保证有足够的空闲进程待命
修改完之后重启PHP-FPM:
brew services restart php@7.2
3. 优化WebSocket服务代码
如果WebSocket进程占用CPU过高,说明代码有问题:
- 尽量用非阻塞IO的PHP库来写WebSocket服务,比如Workerman或者Swoole(Swoole需要装扩展,但PHP7.2支持得很好),比原生的阻塞写法资源占用低很多
- 检查代码里的循环逻辑,有没有无限循环或者不必要的阻塞操作,比如没有处理好客户端断开后的资源释放
4. 验证端口独立性
用lsof命令确认各个服务的端口监听是独立的,没有冲突:
lsof -i :8080 # 检查Nginx lsof -i :9002 # 检查PHP-FPM lsof -i :9090 # 检查WebSocket
确保每个端口对应的进程都是独立的,没有互相占用的情况。
三、验证步骤
- 先停掉WebSocket服务:
pkill -f webSocketServer.php - 重启Nginx和PHP-FPM:
brew services restart nginx brew services restart php@7.2 - 测试8080的API:
curl http://127.0.0.1:8080/api/users,确认能正常返回 - 用后台命令启动WebSocket服务,再次测试API,同时用
top和ps监控进程状态
如果还是有问题,去看Nginx的错误日志(/usr/local/var/log/nginx/error.log),里面会有更详细的504触发原因,比如是连接PHP-FPM超时,还是PHP-FPM处理请求超时,再针对性排查。
内容的提问来源于stack exchange,提问作者mik3fly-4steri5k

