带有 Nodejs 的 Socket.io 不适用于 nginx 反向代理

时间:2021-01-21 21:23:39

标签: node.js nginx socket.io nginx-reverse-proxy

我有一个带有 Express 和 Socket.io (Ubuntu 18.04) 的 Nodejs 服务器应用程序。在 nGinx (1.14) 反向代理进入场景之前,它一直运行良好。 nginx 服务器运行在不同的 Node.js 应用程序机器上,每个应用程序在它自己的虚拟机上,在同一个网络内。

2.1.1 版的服务器和客户端。

nginx 服务器负责多个应用程序重定向。

我尝试了几种配置组合,但没有任何效果。

这是我尝试过的(“company1”的示例):

/etc/nginx/conf.d 中的 default.conf

location /company1-srv/ {
     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-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-Proto $scheme;
     proxy_set_header X-NginX-Proxy true;
     proxy_redirect off;
     proxy_pass http://172.16.0.25:51001/;
}

然后在客户端代码中,我使用“路径”选项进行连接,因为 socket.io 错放了它的库路径。

// companySrv and URL is actually returned by another service (following code is for illustrative purposes):
let companyUrl = 'https://api.myserver.com/company1-srv';
let companySrv = '/company1-srv'; 

socket(companyUrl, {
      path: companySrv + '/socket.io/'
});

我还尝试删除路径选项并为 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_cache_bypass $http_upgrade;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-Proto $scheme;
   proxy_set_header X-NginX-Proxy true;
   proxy_redirect off;
   proxy_pass http://172.16.0.25:51001/socket.io/;
}

没有任何效果。

它连接,但不发射任何东西。不久(一分钟左右)后,它变得不可用,引发“断开连接”(原因:传输关闭)客户端事件。

服务器:

const io = require('socket.io')(https || http, {
   transports: ['polling', 'websocket'],
   allowUpgrades: true, 
   pingInterval: 60000*60*24, 
   pingTimeout: 60000*60*24
});

我还尝试编辑 nginx.conf 并编写“上游 socket_nodes { ...”并使用 proxy_pass http://socket_nodes。这没有意义,因为我需要根据公司的不同进行确切的重定向,但为了进行测试,我做了,但效果不佳。

我需要做什么?

谢谢

1 个答案:

答案 0 :(得分:0)

我们也使用 socket.io 和来自 ngnix 的反向代理。我可以分享一些我们的设置,也许这​​有助于排除问题。

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 768;
}

stream {
        log_format      basic   '$time_iso8601 $remote_addr '
                                '$protocol $status $bytes_sent $bytes_received '
                                '$session_time $upstream_addr '
                                '"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
        
        access_log /var/log/nginx/stream.log basic;
}

http {

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        gzip on;

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;

        ##
        # Server Blocks 
        ##


        # DOMAINEXAMPLE A
        server {
                server_name exampleA.domain.com;
                location / {
                        proxy_set_header        X-Forwarded-For $remote_addr;
                        proxy_set_header        Host $http_host;
                        proxy_pass              http://192.168.21.105:5050;
                 }
        }

        # DOMAINEXAMPLE B
        server {
                server_name exampleB.domain.com;
                location /api {
                        proxy_set_header        X-Forwarded-For $remote_addr;
                        proxy_set_header        Host $http_host;
                        proxy_pass              http://192.168.21.106:5050;
                }
        }

     
}

这里最有趣的部分可能是服务器块

        # DOMAINEXAMPLE A
        server {
                server_name exampleA.domain.com;
                location / {
                        proxy_set_header        X-Forwarded-For $remote_addr;
                        proxy_set_header        Host $http_host;
                        proxy_pass              http://192.168.21.105:5050;
                 }
        }

        # DOMAINEXAMPLE B
        server {
                server_name exampleB.domain.com;
                location /api {
                        proxy_set_header        X-Forwarded-For $remote_addr;
                        proxy_set_header        Host $http_host;
                        proxy_pass              http://192.168.21.106:5050;
                }
        }

域示例 A

对于位于 / 的位置 http://192.168.21.105:5050,我们有一个 NodeJS 进程正在运行,包括 socket.io 的设置

const express = require('express');
const http    = require('http');
const app     = express();
const server  = http.createServer(app);
const io      = require('socket.io')(server);

域示例 B

对于位于 /api 的位置 http://192.168.21.106:5050,我们有另一个 NodeJS 进程正在运行,包括 socket.io 的稍微不同的设置

const express  = require('express');
const http     = require('http');
const app      = express();
const server   = http.createServer(app);
const io       = require('socket.io')(server, {path: '/api/socket.io'});

在这两种情况下,socket.io 对我们来说都很好

从客户端连接(示例 B)

我们在服务器端实际做的是为 socket.io 创建一个命名空间,比如

const io= require('socket.io')(server, {path: '/api/socket.io'});
const nsp = io.of('/api/frontend');

然后在客户端,像这样连接到它

import io from 'socket.io-client'
const socket = io('https://exampleB.domain.com/api/frontend', {path: "/api/socket.io"});