共计 3725 个字符,预计需要花费 10 分钟才能阅读完成。
WebSocket 协议给我们提供了一个创建可以支持客户端和服务端进行双向实时通信的 web 应用程序的方法。相比之前使用的方法,WebSocket(作为 HTML5 的一部分)可以使我们更容易开的发出这种类型的应用程序。绝大多数的现代浏览器都支持 WebSocket,包括火狐,IE,Chrome,Safari 以及 Opera 等,同时,越来越多的服务端框架也开始支持 WebSocket 了。
对于企业应用来说,我们需要多个 WebSocket 服务器来保障性能和高可用性,因此我们迫切的需要对 WebSocket 协议进行负载均衡。NGINX 自从 1.3 版本就开始支持 WebSocket 了,并且可以为 WebSocket 应用程序做反向代理和负载均衡。
WebSocket 和 HTTP 协议不同,但是 WebSocket 中的握手和 HTTP 中的握手兼容,它使用 HTTP 中的 Upgrade 协议头将连接从 HTTP 升级到 WebSocket。这使得 WebSocket 程序可以更容易的使用现已存在的基础设施。例如,WebSocket 可以使用标准的 HTTP 端口 80 和 443,因此,现存的防火墙规则也同样适用。
一个 WebSockets 的应用程序会在客户端和服务端保持一个长时间工作的连接。用来将连接从 HTTP 升级到 WebSocket 的 HTTP 升级机制使用 HTTP 的 Upgrade 和 Connection 协议头。反向代理服务器在支持 WebSocket 方面面临着一些挑战。一项挑战是 WebSocket 是一个 hop-by-hop 协议,所以,当代理服务器拦截到一个客户端发来的 Upgrade 请求时,它 (指服务器) 需要将它自己的 Upgrade 请求发送给后端服务器,也包括合适的请求头。此外,由于 WebSocket 连接是长时间保持的,所以代理服务器需要允许这些连接处于打开状态,而不是像对待 HTTP 使用的短连接那样将其关闭。
NGINX 通过在客户端和后端服务器之间建立起一条隧道来支持 WebSocket。为了使 NGINX 可以将来自客户端的 Upgrade 请求发送给后端服务器,Upgrade 和 Connection 的头信息必须被显式的设置。如下所示:
location /wsapp/ {
proxy_pass http://wsbackend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
一旦我们完成以上设置,NGINX 就可以处理 WebSocket 连接了。
NGINX Websockets 举例
这里有一个展示 NGINX 如何为 WebSocket 做代理的实例。这个例子将会使用 node.js 上的一个实现了 WebSocket 的模块——ws。这个示例在 Ubuntu 13.10 和 CentOS 6.5 上测试通过,但对于其他系统来说也许需要稍作修改。就这个例子来说,WebSocket 服务器的 IP 地址是 192.168.100.10,NGINX 服务器的 IP 地址是 192.168.100.20。如果你还没有安装 node.js 和 npm,你可以通过以下命令安装:
对 Debian/Ubuntu 来说:
sudo apt-get install nodejs npm
对 RHEL/CentOS 来说:
sudo yum install nodejs npm
在 Ubuntu 上,node.js 会被安装为 “nodejs”,在 CentOS 中被会安装为 ”node”。我们在这例子中统一使用 ”node”,所以,我们将会在 Ubuntu 上创建一个连接来允许我们使用“node”:
ln -s /usr/bin/nodejs /usr/local/bin/node
然后安装 ws:
sudo npm install ws
注意:如果你得到了一个错误:“Error: failed to fetch from registry: ws”,那么运行下面的命令应该能解决这个问题:
sudo npm config set registry http://registry.npmjs.org/
接下来,你可以再次运行 sudo npm install ws
ws 命令来自 /root/node_modules/ws/bin/wscat,我们将会把它当做我们的客户端,但是我们需要创建一个程序来做我们的服务端。将下面的代码保存到一个 server.js 文件中:
console.log("Server started");
var Msg = '';
var WebSocketServer = require('ws').Server
, wss = new WebSocketServer({port: 8010});
wss.on('connection', function(ws) {ws.on('message', function(message) {console.log('Received from client: %s', message);
ws.send('Server received from client:' + message);
});
});
这个程序可以通过下面的命令执行:
node server.js
该程序会输出一条初始化消息“Server started”,之后监听 8010 端口,等待客户端的连接。它会处理收到的所有请求,并且将接收到的消息输出在控制台,之后向客户端返回一条包含该消息的消息。我们希望 NGINX 去代理这些请求,通过下面的配置便可实现:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream websocket {server 192.168.100.10:8010;}
server {
listen 8020;
location / {
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
上面的配置会使 NGINX 监听 8020 端口,并把接收到的任何请求传递给后端的 WebSocket 服务器以便恰当的处理 WebSocket 协议。我们可以使用 wscat 作为客户端来测试一下:
/root/node_modules/ws/bin/wscat –connect ws://192.168.100.20:8020
上面的命令会通过 NGINX 代理服务器和 WebSocket 服务器建立连接,你可以输入你想要发送给服务器的消息,之后服务器会返回一条消息。每当你输入一条消息,你应该可以在服务端看到该消息的输出,之后在客户端会显示一条来自服务端的消息。
这是一个交互示例:
Server: | Client: |
$ node server.js | |
Server started | |
wscat –connect ws://192.168.100.20:8020 | |
Connected (press CTRL+C to quit) | |
> Hello | |
Received from client: Hello | |
< Server received from client: Hello |
由此我们可以看到服务端与客户端能够通过作为代理的 NGINX 通信,而且消息可以持续进行双向传输直到客户端或服务端断开连接。为了能使 NGINX 正确处理 WebSocket,只需正确地设置消息头来处理更新从 http 到 WebSocket 连接的 Upgrade 请求。
更多信息请参见:
-
Using NGINX with WebSockets
-
NGINX documentation
-
NGINX and NGINX Plus features
-
NGINX Plus Technical Specifications
CentOS 6.2 实战部署 Nginx+MySQL+PHP http://www.linuxidc.com/Linux/2013-09/90020.htm
使用 Nginx 搭建 WEB 服务器 http://www.linuxidc.com/Linux/2013-09/89768.htm
搭建基于 Linux6.3+Nginx1.2+PHP5+MySQL5.5 的 Web 服务器全过程 http://www.linuxidc.com/Linux/2013-09/89692.htm
CentOS 6.3 下 Nginx 性能调优 http://www.linuxidc.com/Linux/2013-09/89656.htm
CentOS 6.3 下配置 Nginx 加载 ngx_pagespeed 模块 http://www.linuxidc.com/Linux/2013-09/89657.htm
CentOS 6.4 安装配置 Nginx+Pcre+php-fpm http://www.linuxidc.com/Linux/2013-08/88984.htm
Nginx 搭建视频点播服务器(仿真专业流媒体软件)http://www.linuxidc.com/Linux/2012-08/69151.htm
Nginx 的详细介绍:请点这里
Nginx 的下载地址:请点这里