Nginx擔當WebSockets代理


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請求。



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM