2

I am trying to reverse proxy several socket.io websockets and also rewrite the URLs so that I can have a front end server that can connect to several backend tty.js instances.

For example:

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

For HTTP any old proxy works fine. However when I rewrite the URLs instead of the websocket looking like:

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

it looks like:

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

This of course goes unhandled. I assume the rewrite happens and so the socket assumes it's "connection" is at /socket.io/1/?t=1354135029745 instead of /server1/socket.io/1/?t=1354135029745

Is there some way to do URL rewriting as well as proxy a websocket?

So far I have tried both Varnish, node-http-proxy and Nginx using the TCP proxy module and I haven't been able to figure out how to get this to work.

Right now my Varnish config looks like:

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);
}

I am forced to leave out the obligatory:

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

since I have multiple backends. Is there a way to get this to work using node-http-proxy, Nginx or Varnish? Or if none of those have the ability, would something like haproxy or really anything else be able to?

My first inclination would be to set a custom header so when the URL does get rewritten it knows which backend it should hit, but I'm not sure if/how that would work.

Edit 1: I was able to sort of fix this issues by also pulling the req.http.referer and adding that to the socket.io statement:

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

However it appears to be a little wonky and seems to revert socket.io to xhr polling which is not ideal but better than nothing.

Edit 2: After testing it out with a few backends what happens is once long polling starts it breaks the rest of the proxy. As soon as I refresh the page now the reverse proxy instead of going:

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

goes:

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

until I reload varnish and then goes back.

4

1 回答 1

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第一次请求后没有标头

于 2012-12-03T07:17:54.263 回答