You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 07:05:50