使用nginx作为websocket的proxy server
WebSocket
WebSocket协议为创建客户端和服务器端需要实时双向通讯的webapp提供了一个选择。其为HTML5的一部分,WebSocket相较于原来开发这类app的方法来说,其能使开发更加地简单。大部分现在的浏览器都支持WebSocket,比如Firefox,IE,Chrome,Safari,Opera,并且越来越多的服务器框架现在也同样支持WebSocket。
在实际的生产环境中,要求多个WebSocket服务器必须具有高性能和高可用,那么WebSocket协议就需要一个负载均衡层,NGINX从1.3开始支持WebSocket,其可以作为一个反向代理和为WebSocket程序做负载均衡。
WebSocket协议不同于HTTP协议,但是WebSocket握手是通过HTTP来完成的,使用HTTP的Upgrade设施来升级连接从HTTP到WebSocket。这个允许WebSocket程序能够更简单地融入现有的基础设施。比如,WebSocket程序可以使用80和443标准的HTTP端口,从而允许使用存在的防火墙策略。
一个WebSocket程序持有一个长时间运行的在客户端和服务器端之间打开的连接,促进实时应用程序的开发(这个翻译有问题)。被用来升级连接从HTTP到WebSocket的HTTP Upgrade机制使用Upgrade和Connection头部来完成。在反向代理服务器支持WebSocket中,需要面临一些挑战。第一个是WebSocket是一个hop-by-hop协议,所以当代理服务器拦截来至于客服端的一个Upgrade请求时,代理服务器需要发送它自己的Upgrade请求给后端服务器,包括一些合适的头部。同样,因为WebSocket是长时间存活,相反的,HTTP连接是典型的短连接,反向代理服务器必须允许这些连接保持打开,而不是在它们看起来闲置时关闭它们。
nginx
NGINX通过允许一个在客户端和后端服务器之间建立的隧道来支持WebSocket。为了NGINX发送来至于客户端Upgrade请求到后端服务器,Upgrade和Connection头部必须被设置明确。
示例,这个例子在我前面文章中使用过–chatRobot。上次是客户端直接连的express程序,这里我们使用nginx来做代理。
upstream wsbackend {
server 127.0.0.1:3000;
}
server {
listen 8090;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
# location / {
# root html;
# index index.html index.htm;
# }
location / {
proxy_pass http://wsbackend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
我们将qt程序中的链接改一下
const char* server_url = "ws://localhost:8090";
我们的chatRobot还是一样的可以运行。
其实这只是一个简单地接合nginx和nodejs的例子。
这里我总结了几点我们为什么把nginx放在前面的。
- nodejs适合做为restful api接口和动态的页面生成,虽然也有静态资源托管模块,但是会大幅度影响nodejs的性能,但是nginx适合处理静态资源。所以让它们做自己擅长的事。
- 安全,直接在外网暴露nodejs会有很大的风险。
- 卸HTTPS,nginx与客户端连接加密,后端的nodejs和nginx处于内网环境下,可以不加密,这样省去了nodejs卸https的负载。
- nginx作为反向代理和负载均衡,方便后台nodejs的横向扩展。
使用nginx是为了更好地使用nodejs来提供服务。