socket.io 使用多個 node 實例

2018-10-16 19:07 更新

棘手的負載均衡


如果要在不同的進程或主機之間進行連接負載的分發(fā),必須要確保帶有特定 session id 的請求連接到產(chǎn)生該 id 的進程。

這是由于特定的傳輸方式(比如 XHR 輪詢或 JSONP 輪詢)依賴于在 “socket” 的聲明周期中發(fā)送多個請求。

要闡明這么做的原因,可以參考下面的例子。這個例子是要在所有連接到服務器的客戶端上觸發(fā)一個事件:

io.emit('hi', 'all sockets');

可能有些客戶端使用的是雙向通信機制比如 WebSocket ,這樣我們可以立即向其中寫入消息。但是可能還有一些使用的是長輪詢(long-polling)機制。

如果客戶端使用了長輪詢,它們不一定發(fā)送了可以向其中寫入消息的請求。它們可能處于這些請求之間的階段。這種情況下,我們需要在進程中緩存消息。為了讓客戶端能在發(fā)送請求時取回這些消息,最簡單的方法就是讓客戶端連接到同一個進程上。

一種簡單的方式是使用客戶端的原始地址來進行路由。下面的例子使用了 NginX 服務器:

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 設置。

使用 Node.JS 集群


和 NginX 一樣, Node.JS 通過 cluster 模塊提供了內(nèi)置的集群支持。

Fedor Indutny 創(chuàng)建了一個 sticky session 模塊。該模塊確保文件描述符(也就是連接)可以通過來源的 remoteAddress (也就是 IP)進行路由。

在 node 實例之間傳遞事件


假如有多個 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 進程傳遞消息,可以看看“使用外部消息源”.


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號