【问题标题】:Proxing Websocket Traffic from Nginx to Socket.io (without SSL)代理从 Nginx 到 Socket.io 的 Websocket 流量(无 SSL)
【发布时间】:2013-02-05 23:34:02
【问题描述】:

从昨天开始,nginx 开始支持 websocket 连接,因此我试图让我的 nginx-nodejs-socket.io 应用程序在没有 harproxy 等的情况下工作(虽然运气不太好)。

我想要实现的是 nginx 仅将 websocket 连接请求发送到支持的服务器,或者更准确地说是 websocket 服务器,socket.io,同时 nginx 将提供 php 文件和所有静态内容包括 html 文件。我根本不想 express 提供静态内容(如果可能的话)。

这是我的 nginx.conf

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;
events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    gzip  on;

    upstream backend {
        server 127.0.0.1:8080;
    }

    server {
        listen       80;
        server_name  localhost;

        charset UTF-8;

        #access_log  logs/host.access.log  main;

        location / {
            root   /website/html_public;
            index  index.php index.html index.htm;
        }       
        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /website/html_public;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        location ~ \.php$ {
        root           /website/html_public;
        try_files      $uri =404;
        fastcgi_pass   unix:/tmp/php5-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
        }

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        location ~ /\.ht {
            deny  all;
        }

         location /connection {
         proxy_pass http://backend;  
         proxy_http_version 1.1;
         proxy_set_header Upgrade $http_upgrade;
         proxy_set_header Connection "upgrade";
             }
       }

    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   /website/html_public;
    #        index  index.php index.html index.htm;
    #    }
    #}
}

这是我在节点中的 server.js 文件

var express = require('express');
var app     = express();
var port    = 8080;

/* HTTP Server*/

server = require('http').createServer(app);
server.listen(port);
app.use(express.logger(':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms'));
app.use(express.static(__dirname + '/html_public'));
app.use(express.favicon());

app.set('view engine', 'jade');
app.set('view options', { layout: false });
app.set('views', __dirname + '/views');

app.get('/', function(req, res){
    res.render('index.html');

});

/*
* Web Sockets
*/
io   = require('socket.io').listen(server),
io.configure('production', function(){
io.enable('browser client etag');
io.set('log level', 1);
io.set('transports', [ 'websocket', 'htmlfile', 'xhr-polling', 'jsonp-polling' ]);
});


console.log('Chat Server started with Node '+ process.version +', platform '+ process.platform + 'to port %d',port); 

从我的客户那里,我尝试像这样连接:

socket = new io.connect('http://localhost/connection');

现在,问题是当我尝试正常连接时,键入 localhost,我在 chrome 控制台上看到: **GET http://localhost/socket.io/socket.io.js 404 (Not Found)** ,并且当在浏览器中输入 http://localhost/connection 时,我收到 "Cannot GET /connection" 这告诉我 nginx 不能使用我当前的配置正常代理 websockets。

提前感谢您的回答。

【问题讨论】:

  • 为什么要通过 Apache 提供静态内容?这是一个开销。 Nginx也可以做的很好see this question例如
  • @Mustafa 你误解了我不想让 Apache 做任何事情,因为我的项目中根本不存在,我只使用 Nginx,我想你没有仔细阅读我的问题,我展示了我的 nginx .conf 文件。
  • 您的后端是否响应GET /connection 请求?你的服务器上有/website/html_public/socket.io/socket.io.js 文件吗?
  • @VBart 不,我的支持不响应 GET /connection 请求,我在服务器上有 socket.io.js,但它仅在我输入 localhost:8080 时加载,当简单输入 localhost 失败时加载资源(因为 nginx 不代理我假设的 websocket)
  • 但是您没有将 nginx 配置为代理 localhost:8080。相反,您已将 nginx 配置为代理 localhost:8080/connection。如果你输入 localhost:8080/connection 会发生什么?

标签: node.js nginx express websocket socket.io


【解决方案1】:

让我猜,你想要:

location /connection {
    proxy_pass http://backend/;
    ...
}

但你有:

location /connection {
    proxy_pass http://backend;
    ...
}

http://nginx.org/r/proxy_pass

【讨论】:

  • 我按照您的建议更改了 nginx 配置,但是当我键入“localhost:8080/connection”时,我仍然收到“无法获取/连接”消息。我注意到当我只在我的浏览器,socket.io 无法加载,但是输入 ip:8080 时加载正确。可能是我的 server.js 故障,nginx 干扰了 socket.io.js 文件的快速服务?我迷路了!
  • 您还在 Chrome 控制台中看到 GET http://localhost/socket.io/socket.io.js 404 (Not Found) 吗?
  • 不幸的是,只有当我将浏览器指向 localhost:8080(以及从客户端也指向 localhost:8080)时,socket.io.js 才能正常解析:/
  • socket.io.js 是否位于/website/html_public/socket.io/ 目录中?
  • src="./socket.io/socket.io.js" 正好意味着浏览器必须从服务器加载这个脚本。没有魔法。
【解决方案2】:

只是为了确定,你有 Nginx 版本 1.3.13 吗? (例如 Nginx 的 PPA 还没有那个版本。)

【讨论】:

猜你喜欢
  • 2012-05-06
  • 1970-01-01
  • 1970-01-01
  • 2020-11-22
  • 2011-07-22
  • 1970-01-01
  • 2020-02-27
  • 1970-01-01
  • 2021-07-09
相关资源
最近更新 更多