利用Varnish和Nginx来使用WebSocket

大家都知道Nginx是一个阻塞web应用程序的前端web服务器。然而,目前Nginx不支持WebSocket。

我们可以用tcp模块编译Nginx,来代理WebSocket和HTTP通信,并使用不同的后端。这样的话,我们需要手动编译这个过程,这也需要运行多个web应用程序(例如,你的主要应用程序在一个端口,WebSocket的处理在另一个端口)。

一个更好的解决办法是把Nginx放在你的后端web应用程序的前面,而Varnish则放在Nginx的前面。Varnish可被配置为通过WebSocket直接通信到你的后端,并同时发送其余的通信到Nginx。这需要你运行一个单一的后端服务,来处理在同一端口没有Nginx情况下的WebSocket和HTTP通信。

下面是我的后端Web应用程序Gunicorn服务器的设置,我在那里设置了基本的配置命令。你同样也可以运行Node.js、Tornado。

运行Varnish,并开启80端口,编辑以下代码到你的default.vcl文件:

backend nginx {
    .host = "127.0.0.1";
    .port = "8080";
}
backend gunicorn {
    .host = "127.0.0.1";
    .port = "6543";
}
sub vcl_pipe {
    if (req.http.upgrade) {
        set bereq.http.upgrade = req.http.upgrade;
    }
}
sub vcl_recv {
    if (req.http.Upgrade ~ "(?i)websocket") {
        set req.backend = gunicorn;
        return (pipe);
    }
    else {
        set req.backend = nginx;
    }
}

使用你的nginx.conf运行Nginx(你可以查看Gunicorn文档了解更加完整的配置示例):

upstream gunicorn {
    server 127.0.0.1:6543;
}
server {
    listen 8080 default;
    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://gunicorn;
    }
}

一个实现详情的特殊例子,通过Gunicorn配置,让WebSocket知道你的worker_class。例如:

worker_class = 'pyramid_socketio.gunicorn.workers.GeventSocketIOWorker'

其实,更多的问题是你自己的特定后端的实现。只要Varnish和上面Nginx配置在任何的后端部署好,WebSocket就可以工作。

相关推荐