带有 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 代理服务器的 Keycloak 未验证 rest api
docker上带有javascript和nginx的websockets