利用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就可以工作。