我有一个使用 express 和 socket.io 在 node.js 中编写的基本聊天应用程序;当直接连接到端口 3000 上的节点时,它工作正常
但是当我尝试使用 nginx v1.4.2 作为代理时不起作用。
我开始使用连接图
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
然后添加位置
location /socket.io/ {
proxy_pass http://node;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Request-Id $txid;
proxy_set_header X-Session-Id $uid_set+$uid_got;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_buffering off;
proxy_read_timeout 86400;
keepalive_timeout 90;
proxy_cache off;
access_log /var/log/nginx/webservice.access.log;
error_log /var/log/nginx/webservice.error.log;
}
location /web-service/ {
proxy_pass http://node;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Request-Id $txid;
proxy_set_header X-Session-Id $uid_set+$uid_got;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_buffering off;
proxy_read_timeout 86400;
keepalive_timeout 90;
access_log /var/log/nginx/webservice.access.log;
error_log /var/log/nginx/webservice.error.log;
rewrite /web-service/(.*) /$1 break;
proxy_cache off;
}
这些都是使用我能找到的所有技巧来构建的。错误日志没有显示任何错误。(除非我停止节点以测试错误日志是否正常工作)
当通过 nginx 时,我确实在开发工具中看到了一个 websocket 连接,状态为 101;但结果下的框架选项卡是空的。我在响应标头中看到的唯一区别是通过 nginx 的大小写差异 - “upgrade” 与 “Upgrade”:
Connection:upgrade
Date:Fri, 08 Nov 2013 11:49:25 GMT
Sec-WebSocket-Accept:LGB+iEBb8Ql9zYfqNfuuXzdzjgg=
Server:nginx/1.4.2
Upgrade:websocket
直接从节点
Connection:Upgrade
Sec-WebSocket-Accept:8nwPpvg+4wKMOyQBEvxWXutd8YY=
Upgrade:websocket
来自节点的输出(通过 nginx 使用时)
debug - served static content /socket.io.js
debug - client authorized
info - handshake authorized iaej2VQlsbLFIhachyb1
debug - setting request GET /socket.io/1/websocket/iaej2VQlsbLFIhachyb1
debug - set heartbeat interval for client iaej2VQlsbLFIhachyb1
debug - client authorized for
debug - websocket writing 1::
debug - websocket writing 5:::{"name":"message","args":[{"message":"welcome to the chat"}]}
debug - clearing poll timeout
debug - jsonppolling writing io.j[0]("8::");
debug - set close timeout for client 7My3F4CuvZC0I4Olhybz
debug - jsonppolling closed due to exceeded duration
debug - clearing poll timeout
debug - jsonppolling writing io.j[0]("8::");
debug - set close timeout for client AkCYl0nWNZAHeyUihyb0
debug - jsonppolling closed due to exceeded duration
debug - setting request GET /socket.io/1/xhr-polling/iaej2VQlsbLFIhachyb1?t=1383911206158
debug - setting poll timeout
debug - discarding transport
debug - cleared heartbeat interval for client iaej2VQlsbLFIhachyb1
debug - setting request GET /socket.io/1/jsonp-polling/iaej2VQlsbLFIhachyb1?t=1383911216160&i=0
debug - setting poll timeout
debug - discarding transport
debug - clearing poll timeout
debug - clearing poll timeout
debug - jsonppolling writing io.j[0]("8::");
debug - set close timeout for client iaej2VQlsbLFIhachyb1
debug - jsonppolling closed due to exceeded duration
debug - setting request GET /socket.io/1/jsonp-polling/iaej2VQlsbLFIhachyb1?t=1383911236429&i=0
debug - setting poll timeout
debug - discarding transport
debug - cleared close timeout for client iaej2VQlsbLFIhachyb1
当直接到节点时,客户端不会开始轮询。
正常的 http 内容节点输出与 nginx 配合良好。
显然我没有看到一些东西,但是我被卡住了,谢谢:)
答案1
您是否尝试过如下最小配置:
location /socket.io/ {
proxy_pass http://node;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
还要注意从 $http_host 到 $host 的变化,因为它们的值在某些情况下可能会不同: https://stackoverflow.com/questions/15414810/nginx 中的主机和 http 主机的区别是什么
答案2
当我引入 nginx 来代理 Web Socket 时,我也遇到了同样的问题。问题是我在 nodejs 中强制将连接立即设置为 Web Socket。删除此强制后,它首先在轮询中进行协商,然后自动升级:
在客户端我评论了传输:
//transports:['websocket', 'polling'] this was not permiting my connection with nginx
io(this.adress, {query: 'auth_cookie='+this.auth_cookie});
我还删除了服务器端的传输配置。
为了完整性,这是我的 nginx 配置:
server {
listen 80;
server_name demo2.example.com;
location /socket.io {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://demo2.example.com:3012/socket.io;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location / {
proxy_pass http://demo2.example.com:81;
}
}
希望这可以帮助