nginx 代理 websockets,肯定是缺少了什么东西

nginx 代理 websockets,肯定是缺少了什么东西

我有一个使用 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;

  }
}

希望这可以帮助

相关内容