Nodejs + Socket.io + Nginx反向代理不起作用

时间:2019-05-09 17:56:59

标签: node.js nginx socket.io

我正在将Nginx反向代理设置为包含托管其他NodeJs应用程序的服务器上包含Socket.IO的NodeJS应用程序。

NodeJS通过PM2在端口3001上运行。这是Nginx配置:

server {
        listen 80;
        server_name iptv-staging.northpoint.org;
        location / {
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;

                proxy_pass http://localhost:3001;

                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
        }
}

通过服务器的IP地址直接http://xxx.xxx.xxx.xxx:3001/运行应用程序时,所有程序运行都没有问题。来自Socket.IO的Ping / Pong请求大约为50ms(默认pingTimeout为5000ms)。通过其DNS名称http://iptv-staging.northpoint.org访问该应用程序时,客户端会报告ping超时并断开连接。它将在第一次尝试时重新连接,然后在第一个ping / pong请求中再次断开连接。

据我所知,问题必须与Ngnix反向代理以及Websocket的路由方式有关。似乎服务器对ping请求的答复并未传递给客户端。但我似乎无法确定原因。非常感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

我有完全一样的问题。一个工作的人提供了答案,说实话,我并没有完全理解,所以对我没有任何信誉,但是我希望我可以从我的代码中挑出来答案。

首先,我在返回URI信息的服务器上创建了一个API端点。这是告诉客户端使用哪个地址进行连接的关键。

apiRoutes.get('/options', (req, res) => {

  Log.info('Received request for app options.');

  // This isn't applicable to you, just showing where options declared.
  let options = JSON.parse(JSON.stringify(config.get('healthcheck.options')));

  // Decide what port to use.  It might be a port for a dev instance or from Env
  if ((process.env.PORT !== options.port) && (process.env.PORT > 0)) {
    options.port = process.env.PORT;
  }

  // This is the important bit...
  var internalUri = req.originalUrl;
  var externalUri = req.get('X-Real-URI') || internalUri;
  options.basePath = externalUri.substr(0, externalUri.length - internalUri.length + 1);

  res.status(200).send(JSON.stringify(options));
});

我的客户是一个React应用,您会考虑如何实现,但这就是我的实现方式。

这是我的“帮助”功能,用于调用“选项”服务...

export async function getOptions() {

  const res = await axios.get('/api/options');

  return res.data;

}

在我的React页面中,当页面加载时,我将其称为...

componentDidMount() {

    getOptions()
        .then((res) => {
            this.setState({ port: res.port });

        // Call a client-side function to build URL.  Incl later.
        const socketUrl = getSocketUrl(res.port);

        console.log(`Attempting to connect to sockets at ${socketUrl}.`);

        // This is where it all comes together...
        const socket = io(socketUrl, { path: `${res.basePath}socket.io` });
        socket.on('connect', function () { console.log(`Connected to ${socketUrl}`); });

        socket.on('message', (result) => {
          console.log(result);
        });

        socket.on('data', (result) => {
          console.log(`Receiving next batch of results.`);

          const filteredResults = JSON.parse(result));

          // Do something with the results here...

        });

    });

.....

最后,getSocketUrl函数...

function getSocketUrl(port) {

  console.log(`${window.location.hostname}`);

  if (window.location.hostname.toString().includes('local')) {
    return `localhost:${port}`;
  }

  return `${window.location.hostname}`;

}