Nginx 不能用 PHP-FPM 处理 WebSocket 握手,因 PHP-FPM 仅支持短连接 HTTP,不支持 Upgrade 协议升级;正确做法是通过 location 路径分流:/ws 等路径 proxy_pass 至独立 WebSocket 服务(如 6001 端口),.php 请求交由 fastcgi_pass 处理,两者互不干扰。

Nginx 本身不处理 PHP-FPM 的 WebSocket 握手——因为 PHP-FPM 是 FastCGI 协议的后端,不支持 WebSocket 协议升级。WebSocket 必须由独立的长连接服务(如 Node.js、Swoole、Workerman、Laravel Echo Server 等)提供,而 PHP-FPM 只能响应传统 HTTP 请求(短连接、无状态)。所以,“用 PHP-FPM 支持 WebSocket 握手”这个前提不成立,配置上也不能也不该把 WebSocket 路径 proxy_pass 给 php-fpm。
真正要做的,是让 Nginx 正确代理 WebSocket 请求到 真正的 WebSocket 服务,同时把普通 PHP 页面请求交给 PHP-FPM;两者共存于同一域名下,靠 location 路径区分。
✅ 正确的架构分工
-
/ws、/api/ws、/socket.io等路径 → 代理给http://127.0.0.1:6001(或http://backend-ws:8080)等 WebSocket 服务 -
/、/index.php、.php文件 → 交由fastcgi_pass php-fpm处理
Nginx 不“转换”协议,只做路径分流 + 协议透传(Upgrade/Connection 头必须原样转发)。
✅ WebSocket 代理必须的 Nginx 配置(放在对应 location 块内)
location /ws {
proxy_pass http://127.0.0.1:6001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 关键:防止空闲断连(默认 60 秒会杀掉连接)
proxy_read_timeout 86400;
proxy_send_timeout 86400;
# 可选:禁用缓冲,避免消息延迟(尤其对心跳敏感时)
proxy_buffering off;
}⚠️ 注意:
立即学习“PHP免费学习笔记(深入)”;
- 所有
proxy_*指令必须写在location /ws { ... }块里,不能放在server或http级别,否则不生效 -
proxy_http_version 1.1缺失 →$http_upgrade为空 → 后端收不到Upgrade: websocket→ 握手失败 -
Connection "upgrade"必须是固定字符串"upgrade",不是$http_connection(Connection 是逐跳头,不可继承)
✅ PHP-FPM 的常规配置(与 WebSocket 并存,互不干扰)
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock; # 或 127.0.0.1:9000
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}只要路径不重叠(比如 /ws 不匹配 \.php$),Nginx 就会按优先级精准路由:
- 请求
/ws/connect→ 进入location /ws→ 走 proxy_pass - 请求
/api/user.php→ 进入location ~ \.php$→ 走 fastcgi_pass
❌ 常见错误配置(务必避免)
- 把
proxy_pass指向fastcgi://...或php-fpm地址 → FastCGI 不理解Upgrade头,直接返回 502 或 400 - 在
location /块里配 WebSocket 参数 → 所有 PHP 请求也会被加上Upgrade头,导致后端报错 - 忘记设
proxy_read_timeout→ 连接建立后 60 秒无数据就断开,心跳失效 - 使用
proxy_set_header Connection $http_connection→ 客户端可能发keep-alive,Nginx 错误转发导致升级失败
不复杂但容易忽略



















