且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Nginx担当WebSockets代理

更新时间:2022-09-13 13:12:44


Nginx担当WebSockets代理

英文原文:http://nginx.com/blog/websocket-nginx/

作者:chszs,转载需注明。

博客主页:http://blog.csdn.net/chszs

WebSocket 协议提供了一种创建支持client和服务端实时双向通信Web应用程序的方法。作为HTML5规范的一部分,WebSockets简化了开发Web实时通信程序的难度。

眼下主流的浏览器都支持WebSockets,包含火狐、IE、Chrome、Safari以及Opera等,并且,越来越多的server应用框架也開始支持WebSockets。

要在企业产品中使用WebSockets,为满足高性能和高可用性,须要多个WebSocketserver。负载均衡层须要支持WebSocket协议。

Nginx从1.3版起就開始支持WebSocket协议,并且能够担当WebSocket应用程序的反向代理以及实现负载均衡。

WebSocket协议和HTTP协议不同,可是WebSocket协议的握手和HTTP是兼容的,它使用HTTP的Upgrade协议头将连接从HTTP连接升级到WebSocket连接。

这个特性使得WebSocket应用程序能够非常easy地应用到现有的基础设施。比如,WebSocket应用能够使用标准的80和443 HTTPport,因此能够通过现有的防火墙设施。

WebSockets应用程序会在client和server之间建立一个长连接,使得开发实时应用非常easy。

HTTP的Upgrade协议头机制用于将连接从HTTP连接升级到WebSocket连接。Upgrade机制使用了Upgrade协议头和Connection协议头。反向代理server在支持WebSocket协议方面面临着一些挑战。挑战之中的一个是WebSocket是一个逐段转发(hop-by-hop)协议。因此当代理server拦截到来自client的Upgrade请求时,代理server须要将自己的Upgrade请求发送给后端server,包含适合的请求头。并且。由于WebSocket连接是长连接,与传统的HTTP端连接截然不同,故反向代理server还须要同意这些连接处于打开(Open)状态,而不能由于其空暇就关闭了连接。



Nginx通过在client和后端server之间建立隧道来支持WebSockets通信。为了让Nginx能够将来自client的Upgrade请求发送到后端server。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做代理的。

此例将使用ws模块,它是基于node.js构建的WebSocket实现。Nginx将担当反向代理server,后端server是一个使用了ws和Node.js的简单WebSockets应用。样例使用的命令在Ubuntu 13.10和CentOS 6.5上測试通过。但对于其它操作系统也许须要稍作改动。

就这个样例来说,WebSocketserver的IP地址是192.168.100.10,Nginxserver的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,我们会为client使用它,可是我们须要创建一个程序来作为我们的server。将以下的代码保存到一个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”,之后监听8010port。等待client的连接。

它会处理收到的全部请求,并且将接收到的消息输出在控制台。之后向client返回一条包含该消息的消息。我们希望Nginx去代理client的请求,能够通过以下的配置实现:

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监听8020port,并把不论什么接收到的请求转发给后端的WebSocketserver。让后端server更好地处理WebSocket协议。

我们能够使用wscat作为client来測试一下:

/root/node_modules/ws/bin/wscat –connect ws://192.168.100.20:8020

上面的命令会通过Nginx反向代理server和后端WebSocketserver建立连接,你能够向server发送随意消息,然后server会返回一条消息。每当你在client发送一条消息,在后端server上能看到该消息的输出,之后在client会显示一条来自服务端的消息。
这是一个交互演示样例:

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


由此我们能够看到client与server能通过Nginx反向代理建立WebSockets通信,并且消息能够持续地进行双向传输。直至client或server断开连接。为了让Nginx能正确处理WebSocket连接,仅仅需正确地设置消息头来处理从HTTP连接升级到WebSocket连接的Upgrade请求。




本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5413786.html,如需转载请自行联系原作者