Ubuntu下MERN项目Socket.io无法连接,Nginx配置问题求助
Socket.io连接失败排查与修复
我在Ubuntu环境用MERN栈部署了Socket.io项目,通过Nginx和PM2管理,但客户端与服务器无法建立连接,推测问题出在Nginx的location配置上。当前服务器控制台仅输出启动信息,io.connection函数未触发,看不到"New client connected"日志。
客户端代码
//REACT_APP_API_URL = 'http://192.168.109.33:4000/api'; var connectionOptions = { path:'/socket.io', }; const socket = socketIOClient(process.env.REACT_APP_API_URL,connectionOptions);
服务端代码
const express = require("express"); const app = express(); const http = require("http"); const server = http.createServer(app); const bodyParser = require("body-parser"); const socketIo = require("socket.io"); const cors = require("cors"); const PORT = 4000; app.use(bodyParser.json({ limit: "10mb", extended: true })); app.use(bodyParser.urlencoded({ limit: "10mb", extended: true })); app.use(cors({ origin: true })); console.log("visited"); server.listen(PORT, function () { console.log("Server is running on Port: " + PORT); }); let io = socketIo(server, { path:'/socket.io', cors: { origin: "http://servemirates.com", methods: ["GET", "POST"], transports: ["polling"], credentials: true }, allowEIO4: true }); io.on("connection", (socket) => { console.log("New client connected"); socket.io = io; });
Nginx配置
upstream loadbalancer { least_conn; server localhost:4000 max_fails=3 fail_timeout=30s; keepalive 8; } server { index index.html index.html; server_name 35.168.132.12; location / { root /var/www/MernStack-rota/frontend/build/; try_files $uri $uri/ /index.html; } location /api/ { proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $http_host; add_header Cache-Control "no-cache, private, no-store, must-revalidate, max-stale=0"; proxy_pass http://localhost:4000/; proxy_buffering on; } location /socket.io/ { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_pass http://localhost:4000/socket.io/; } location ~ /\.(?!well-known).*{ deny all; } }
当前控制台输出
visited Server is running on Port:4000
期望控制台输出
visited Server is running on Port:4000 New client connected
问题排查与修复方案
1. 客户端连接地址错误
客户端当前用带/api的地址作为Socket.io连接入口,会导致请求路径变为/api/socket.io,但Nginx和服务端监听的都是/socket.io路径,无法匹配。
修复:修改客户端环境变量为不带/api的访问地址:
REACT_APP_API_URL = 'http://35.168.132.12'; // 对应Nginx的server_name // 若用域名访问则改为http://servemirates.com var connectionOptions = { path:'/socket.io', }; const socket = socketIOClient(process.env.REACT_APP_API_URL,connectionOptions);
2. Nginx Socket.io配置优化
当前配置存在两处可优化点:一是未使用定义好的loadbalancer上游服务,二是缺少WebSocket必需的缓存绕过设置。
修改后的Nginx socket.io location配置:
location /socket.io/ { 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_pass http://loadbalancer/socket.io/; proxy_cache_bypass $http_upgrade; proxy_buffering off; # 关闭缓冲避免Socket.io消息延迟 }
3. 服务端CORS范围不匹配
服务端Socket.io仅允许http://servemirates.com跨域,但客户端实际通过IP35.168.132.12访问,会被CORS规则拦截。
修复:扩展CORS允许的源地址:
let io = socketIo(server, { path:'/socket.io', cors: { origin: ["http://servemirates.com", "http://35.168.132.12"], // 同时允许域名和IP访问 methods: ["GET", "POST"], transports: ["polling", "websocket"], // 显式支持WebSocket传输 credentials: true }, allowEIO4: true });
4. 验证服务运行状态
确保PM2进程正常启动,端口4000处于监听状态:
pm2 list # 查看PM2进程状态 netstat -tulpn | grep 4000 # 检查端口监听情况
内容的提问来源于stack exchange,提问作者Heracles Siiz
相关产品推荐
相关产品推荐

