如果要在不同的進程或主機之間進行連接負載的分發(fā),必須要確保帶有特定 session id 的請求連接到產(chǎn)生該 id 的進程。
這是由于特定的傳輸方式(比如 XHR 輪詢或 JSONP 輪詢)依賴于在 “socket” 的聲明周期中發(fā)送多個請求。
要闡明這么做的原因,可以參考下面的例子。這個例子是要在所有連接到服務器的客戶端上觸發(fā)一個事件:
io.emit('hi', 'all sockets');
可能有些客戶端使用的是雙向通信機制比如 WebSocket
,這樣我們可以立即向其中寫入消息。但是可能還有一些使用的是長輪詢(long-polling)機制。
如果客戶端使用了長輪詢,它們不一定發(fā)送了可以向其中寫入消息的請求。它們可能處于這些請求之間的階段。這種情況下,我們需要在進程中緩存消息。為了讓客戶端能在發(fā)送請求時取回這些消息,最簡單的方法就是讓客戶端連接到同一個進程上。
一種簡單的方式是使用客戶端的原始地址來進行路由。下面的例子使用了 NginX 服務器:
在 nginx.conf
文件的 http { }
塊中,可以聲明一個 upstream
塊,里面聲明一個需要進行負載均衡的 Socket.IO 進程列表:
upstream io_nodes {
ip_hash;
server 127.0.0.1:6001;
server 127.0.0.1:6002;
server 127.0.0.1:6003;
server 127.0.0.1:6004;
}
注意 ip_hash
指令表明這些連接是持久的。
同樣在 http { }
塊中,還可以聲明一個 server { }
來指向這個 upstream。為了讓 NginX 支持并轉(zhuǎn)發(fā) WebSocket
協(xié)議,可以明確傳遞必需的 Upgrade
消息頭:
server {
listen 3000;
server_name io.yourhost.com;
location / {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_pass http://io_nodes;
}
}
請確保在最頂層配置了 worker_processes
參數(shù),來指定 NginX 使用的工作進程數(shù)量。你還可以在 events { }
塊中調(diào)節(jié) worker_connections
設置。
和 NginX 一樣, Node.JS 通過 cluster
模塊提供了內(nèi)置的集群支持。
Fedor Indutny 創(chuàng)建了一個 sticky session 模塊。該模塊確保文件描述符(也就是連接)可以通過來源的 remoteAddress
(也就是 IP)進行路由。
假如有多個 Socket.IO 的 node 實例同時提供服務,而你要廣播事件給所有人(或者特定房間里的所有人),你需要某種機制來在進程或主機之間傳遞消息。
這種消息路由的接口我們稱之為 Adapter
(適配器)。你可以在 socket.io-adapter 之上實現(xiàn)自己的適配器(通過繼承),或者直接使用我們提供的基于 Redis 的適配器: socket.io-redis:
var io = require('socket.io')(3000);
var redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));
如果你需要從非 socket.io 進程傳遞消息,可以看看“使用外部消息源”.
更多建議: