带有 nginx 的 Socket.io

Posted

技术标签:

【中文标题】带有 nginx 的 Socket.io【英文标题】:Socket.io with nginx 【发布时间】:2015-05-16 14:56:31 【问题描述】:

我正在尝试通过 nginx 1.6 提供静态文件,并使用 socket.io 代理来自 Node.js Web 服务器的套接字流量。

这是nginx.conf的相关部分:

location /socket.io/ 
            proxy_pass http://localhost:3000;       
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_set_header Host $host;
        

它直接在浏览器和 Node.js 之间完美运行,但是 socket.io 在使用 nginx 1.6 代理时花费的时间太长。握手协议需要花费太多时间,但如果不中断,它最终会在几分钟后开始工作。

通过 nginx 传递静态文件完美运行。

可能是什么问题?

更新:

我分析了一下网络流量,确定以下请求持续了大约一分钟(正是请求升级的时间):

Sec-WebSocket-Key: LhZ1frRdl+myuwyR/T03lQ==
Cookie: io=1-A7tpvwmoGbrSvTAAA5
Connection: keep-alive, Upgrade
Upgrade: websocket
....

预期的响应是代码 101 并且:

Connection: upgrade
Sec-WebSocket-Accept: HXx3KKJadQYjDa11lpK5y1nENMM=
Upgrade: websocket
...

相反,浏览器收到 400 并且:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:8888
Connection: keep-alive
Content-Type: application/json
Server: nginx/1.6.2
Transfer-Encoding: chunked

更新 2:

我确定相同的配置在我的办公室计算机上完美运行,这意味着这是我家用计算机的问题。无论如何,确定到底出了什么问题会非常好。

【问题讨论】:

家庭和办公系统的系统配置差别大吗? 【参考方案1】:

在一个正在运行的服务器中,这里使用的 nginx 的配置是:

  # Requests for socket.io are passed on to Node on port 3000
  location ~* \.io 
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-NginX-Proxy false;

      proxy_pass http://localhost:3000;
      proxy_redirect off;

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

【讨论】:

感谢“hay Seuss”、亚伯拉罕神父、佛陀和地球母亲! Beachfront.Digital 谢谢你。 像魅力一样工作。 3 年多过去了,仍然像魅力一样工作!谢谢 非常感谢。我不敢相信我花了几个月的时间试图弄清楚这一点。像魅力一样工作! 这是救生员。谢谢。【参考方案2】:

你仍然有问题,就像我做的那样,这是你需要做的:对齐 3 个配置。假设您想通过“mysocket”进行通信:

niginx:

  location /mysocket/ 
      proxy_pass http://localhost:3000; 
      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;
    

nodejs:

const io = require('socket.io')(server, 
  path: '/mysocket'
);

客户:

var io = require('socket.io-client');
const socket = io('http://myserver.com, 
    path: '/mysocket'
);

【讨论】:

我没有意识到需要传递给服务器的路径,你在那里解决了我的问题。但是您的 server 变量代表什么?没有它我的工作正常。 @JamesBatchelor 模块“http”的简单 http 服务器。变量服务器是可选的【参考方案3】:

我见过的每个示例(Nginx docs、Nginx blog)都使用:

proxy_set_header Connection "upgrade";

注意所有小写的“升级”。你的例子有一个大写的“U”。也许值得一试。

【讨论】:

【参考方案4】:

看看吧!这里最重要的部分是这 2 个迹象 ^~ 已经失去了 3 天,直到我设法让 nginx 与 socketio 工作..

location ^~ /socket 
            proxy_pass http://localhost:3001;
            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;

【讨论】:

您的客户端和服务器文件是什么样的?还有什么版本的socket.io,我已经第三天了!【参考方案5】:

如何修复WebSocket在连接建立之前关闭。

在本地回答我的套接字 io 连接工作正常,但在生产中,它不工作,出现错误 WebSocket 错误

我通过在我的 Nginx conf 中添加此配置部分来解决此问题

            proxy_pass http://localhost:3001;
            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;
```

【讨论】:

【参考方案6】:

您可能忘记关闭 proxy_redirect;

location / 
            proxy_pass http://localhost:3000/;
            include proxy_params;
            proxy_redirect off;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
    

编辑:

我的来源:https://www.nginx.com/blog/websocket-nginx/

RFC 声明“升级”https://www.rfc-editor.org/rfc/rfc6455#section-1.2

 ...
   The handshake from the client looks as follows:

    GET /chat HTTP/1.1
    Host: server.example.com
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
    Origin: http://example.com
    Sec-WebSocket-Protocol: chat, superchat
    Sec-WebSocket-Version: 13

来自服务器的握手如下所示:

    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
    Sec-WebSocket-Protocol: chat
...

但也说:

   ....
   3.  If the response lacks a |Connection| header field or the
   |Connection| header field doesn't contain a token that is an
   ASCII case-insensitive match for the value "Upgrade", the client
   MUST _Fail the WebSocket Connection_.
   ....

所以是的,每个标头都应该不区分大小写,但是有些服务器(如 Microsoft IIS / 或开发人员特定的实现)不区分大小写。

这一切都取决于nginx之后的底层服务器,它是否接受不区分大小写。

【讨论】:

以上是关于带有 nginx 的 Socket.io的主要内容,如果未能解决你的问题,请参考以下文章

带有 nginx 的 Socket.io

带有 NGINX 代理服务器的 Keycloak 未验证 rest api

docker上带有javascript和nginx的websockets

带有两种 SSL 到 weblogic 的 nginx 反向代理

带有斜杠的奇怪 Nginx 行为

带有 NGINX 和 http 2 的 Socket.io