使用URL重写反向代理socket.io websocket

时间:2012-11-28 22:02:44

标签: nginx websocket socket.io reverse-proxy varnish

我正在尝试反向代理几个socket.io websockets并重写URL,以便我可以拥有一个可以连接到多个后端tty.js实例的前端服务器。

例如:

http://mysite.com/server1 reverse proxies to http://server1/ which is running tty.js

http://mysite.com/server2 reverse proxies to http://server2/ which is running tty.js

对于HTTP,任何旧代理都可以正常工作。但是当我重写URL而不是websocket看起来像:

http://mysite.com/server1/socket.io/1/?t=1354135029745 -> http://server1/socket.io/1/?t=1354135029745

看起来像:

http://mysite.com/socket.io/1/?t=1354135029745

这当然没有处理。我假设重写发生,因此套接字假设它的“连接”在/socket.io/1/?t=1354135029745而不是/server1/socket.io/1/?t=1354135029745

有没有办法进行URL重写以及代理websocket?

到目前为止,我已经使用TCP代理模块尝试了Varnish,node-http-proxy和Nginx,但我还没弄清楚如何让它工作。

现在我的Varnish配置看起来像:

backend backend1 {
    .host = "1.1.1.1";
    .port = "8080";
    .connect_timeout = 1s;
    .between_bytes_timeout = 60s;
    .max_connections = 800;
}

backend backend2 {
    .host = "2.2.2.2";
    .port = "8080";
    .connect_timeout = 1s;
    .between_bytes_timeout = 60s;
    .max_connections = 800;
}

sub vcl_recv {
    set req.grace = 120s
    if(req.url ~ "^/server1/") {
       set req.url = regsub(req.url, "^/server1/", "/");
       set req.backend = backend1;
       return(pipe);
    }
    if(req.url ~ "^/server2/") {
       set req.url = regsub(req.url, "^/server2/", "/");
       set req.backend = backend2;
       return(pipe);
    }
}

sub vcl_pipe {
    if(req.http.upgrade) {
        set bereq.http.upgrade = req.http.upgrade;
    } else {
        set bereq.http.connection = "close";
    }
    return(pipe);
}

我被迫放弃了强制性的要求:

 if(req.url ~ "^/socket.io/") {
    set req.backend = backend1;
    return(pipe);
 }

因为我有多个后端。有没有办法使用node-http-proxy,Nginx或Varnish来实现这一点?或者,如果这些人都没有能力,那么haproxy还是其他任何东西都可以吗?

我的第一个倾向是设置一个自定义标题,所以当URL被重写时,它知道它应该命中哪个后端,但我不确定它是否/如何起作用。

编辑1:我还可以通过拉取req.http.referer并将其添加到socket.io语句来解决这个问题:

if(req.url ~ "^/socket.io/" && req.http.referer ~ "server1"){
   set req.backend = backend1;
   return(pipe);
}

然而它似乎有点不稳定,似乎将socket.io恢复为xhr轮询,这不是理想的,但总比没有好。

编辑2:用一些后端测试后发生的事情是,一旦长轮询开始,就会破坏代理的其余部分。一旦我现在刷新页面反向代理而不是去:

http://mysite.com/server1 -> http://server1

云:

http://mysite.com/ -> http://server1

直到我重新加载清漆然后再回来。

1 个答案:

答案 0 :(得分:0)

您很可能还需要更改Host:中的vcl_recv()标题:

sub vcl_recv {
    set req.grace = 120s
    if(req.url ~ "^/server1/") {
       set req.url = regsub(req.url, "^/server1/", "/");
       set req.http.host = "server1";
       set req.backend = backend1;
       return(pipe);
    }
    if(req.url ~ "^/server2/") {
       set req.url = regsub(req.url, "^/server2/", "/");
       set req.http.host = "server2";
       set req.backend = backend2;
       return(pipe);
    }
}

这应该照顾你的初始问题。

然而,在Varnish中使用管道有一些陷阱,您可能需要考虑这些陷阱。其中最重要的是缺少X-Forwarded-For header after the first request