WebSocket协议提供了一种创建支持客户端和服务器之间实时双向通信的 Web应用的方法。 作为 HTML5 的一部分,WebSocket 使开发这些类型的应用变得比以前的方法容易得多。 大多数现代浏览器都支持 WebSocket,包括 Chrome、Firefox、Internet Explorer、Opera 和 Safari,而且越来越多的服务器应用框架现在也支持 WebSocket。
对于企业生产用途,需要多个 WebSocket 服务器来提高性能和高可用性,因此需要一个理解 WebSocket 协议的负载均衡层,NGINX 从 1.3 版本开始就支持 WebSocket,可以充当反向代理并对 WebSocket应用进行负载均衡。 (NGINX Plus 的所有版本也支持 WebSocket。)
查看有关 NGINX 可扩展性的最新性能测试,以平衡 WebSocket 连接的负载。
WebSocket 协议与 HTTP 协议不同,但是 WebSocket 握手与 HTTP 兼容,使用 HTTP 升级功能将连接从 HTTP 升级到 WebSocket。 这使得 WebSocket应用更容易融入现有基础设施。 例如,WebSocket应用可以使用标准 HTTP 端口 80 和 443,从而允许使用现有的防火墙规则。
WebSocket应用在客户端和服务器之间保持长时间运行的连接,从而有助于实时应用的开发。 用于将连接从 HTTP 升级到 WebSocket 的 HTTP 升级机制使用升级
和连接
标头。 反向代理服务器在支持 WebSocket 方面面临一些挑战。 一是 WebSocket 是一种逐跳协议,因此当代理服务器拦截来自客户端的升级请求时,它需要将自己的升级请求(包括适当的标头)发送到后端服务器。 此外,由于 WebSocket 连接是长寿命的,与 HTTP 使用的典型的短寿命连接相反,反向代理需要允许这些连接保持打开状态,而不是因为它们似乎处于空闲状态而关闭它们。
NGINX 通过允许在客户端和后端服务器之间建立隧道来支持 WebSocket。 为了让 NGINX 将升级请求从客户端发送到后端服务器,必须明确设置升级
和连接
标头,如下例所示:
位置 /wsapp/ { proxy_pass http://wsbackend;
proxy_http_version 1.1;
proxy_set_header 升级 $http_upgrade;
proxy_set_header 连接“升级”;
proxy_set_header 主机 $host;
}
一旦完成后,NGINX 会将其作为 WebSocket 连接处理。
这是一个实时示例,展示 NGINX 作为 WebSocket 代理工作。 此示例使用ws ,一个基于Node.js构建的 WebSocket 实现。 NGINX 作为利用ws和 Node.js 的简单 WebSocket应用的反向代理。 这些说明已经在 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 安装 nodejs npm
对于 RHEL 和 CentOS:
$ sudo yum 安装 nodejs npm
Node.js 在 Ubuntu 上安装为nodejs
,在 CentOS 上安装为node
。 该示例使用node
,因此在 Ubuntu 上我们需要创建从nodejs
到node 的
符号链接:
$ ln -s /usr/bin/nodejs /usr/local/bin/node
要安装ws ,请运行以下命令:
$ sudo npm install ws
笔记: 如果您收到错误消息: “错误:无法从注册表中获取:ws”,运行以下命令来修复问题:
$ sudo npm config 设置注册表http://registry.npmjs.org/
然后再次运行sudo npm install ws
命令。
ws附带了程序/root/node_modules/ws/bin/wscat ,我们将使用它作为客户端,但我们需要创建一个程序来充当服务器。 创建一个名为server.js的文件,内容如下:
console.log("服务器已启动");
var Msg = '';
var WebSocketServer = require('ws').Server
, wss = new WebSocketServer({port: 8010});
wss.on('connection', function(ws) {
ws.on('message', function(message) {
console.log('从客户端接收: %s', message);
ws.send('服务器从客户端接收: ' + message);
});
});
$节点服务器.js
服务器打印初始的“服务器
已启动”
消息,然后监听端口 8010,等待客户端连接。 当它收到客户端请求时,它会回应该请求并将包含收到的消息的消息发送回客户端。 为了让 NGINX 代理这些请求,我们创建以下配置。 我们正在添加地图块
,以便当请求中的升级
标头设置为''
时,连接
标头正确设置为关闭
。
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
上游 websocket {
server 192.168.100.10:8010;
}
server {
listen 8020;
location / {
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header 升级 $http_upgrade;
proxy_set_header 连接 $connection_upgrade;
proxy_set_header 主机 $host;
}
}
}
NGINX 监听端口 8020 并将请求代理到后端 WebSocket 服务器。 proxy_set_header
指令使 NGINX 能够正确处理 WebSocket 协议。
为了测试服务器,我们运行wscat作为客户端:
$ /root/node_modules/ws/bin/wscat --connect ws://192.168.100.20:8020
wscat通过 NGINX 代理连接到 WebSocket 服务器。 当您键入一条消息让 wscat 发送到服务器时,您会看到该消息在服务器上回显,然后来自服务器的消息出现在客户端上。 以下是一个交互示例:
服务器: | 客户: |
---|---|
$ 节点服务器.js 服务器已启动 |
|
|
wscat --connect ws://192.168.100.20:8020 |
从客户端收到: 你好 |
|
< 服务器从客户端收到: 你好 |
这里我们看到客户端和服务器能够通过充当代理的 NGINX 进行通信,并且消息可以继续来回发送,直到客户端或服务器断开连接。 要让 NGINX 正确处理 WebSocket,只需正确设置标头以处理将连接从 HTTP 升级到 WebSocket 的升级请求。
配置 WebSocket 流量的代理:
“这篇博文可能引用了不再可用和/或不再支持的产品。 有关 F5 NGINX 产品和解决方案的最新信息,请探索我们的NGINX 产品系列。 NGINX 现在是 F5 的一部分。 所有之前的 NGINX.com 链接都将重定向至 F5.com 上的类似 NGINX 内容。”