簡體   English   中英

當套接字 io 在 NGNIX 負載均衡器上運行但在使用 pm2 的 fork 上運行時,如何在節點 js 多集群模式下共享全局變量?

[英]How to share a global variable in node js multi cluster mode when socket io is running on NGNIX load balancer but on fork using pm2?

我有一個使用 NGNIX 負載平衡運行的套接字 io 應用程序,我的應用程序在 6 個內核上運行,負載分布在這些內核上。 當我執行pm2 list myapp時,由於 nginx 負載平衡,它顯示它在 fork 模式下運行但跨越 6 個進程

│ myapp-1         │ 21  │ fork │ 
│ myapp-2         │ 45  │ fork │
│ myapp-3         │ 32  │ fork │
│ myapp-4         │ 11  │ fork │ 
│ myapp-5         │ 911  │ fork │ 
│ myapp-6         │ 101 │ fork │ 

這是我的 ngnix 文件的外觀示例

# Nodes for load balancing myapp
upstream myapp_nodes{
    ip_hash;
    server 1.2.3.4:1001;
    server 1.2.3.4:1002;
    server 1.2.3.4:1003;
    server 1.2.3.4:1004;
    server 1.2.3.4:1005;
    server 1.2.3.4:1006;
}

在我的 myapp.js 中,我有一個名為Queue的全局變量,當用戶進入頁面並等待與另一個人連接時,它會存儲用戶。 當其他人來時,老人從隊列中彈出,他們共享一個共同的 ID 一起聊天。 然后我使用第一個人的socket.id作為房間。

示例代碼


var Queue = []; //global array of people waiting to chat

    socket.on("newUserJoinedFromClient", function (Username) {


      //check if someone is already waiting then pop it and return the pop SID as room
      if (Queue.length > 0) {
        var partner = Queue.pop();
        //remove special char from SID
        var room = partner.id.replace(/[^a-zA-Z0-9]/g, "");

        //return and tell the client its room
        socket.emit('sendRoomToClient', {
          room: room,
          users: numUsers
        }); //this person room will be same as the waiting partner room
      }
      // if nobody is in queue, queue is empty
      else {
        //add this user socket id to queue
        Queue.push(socket);
        //remove special char from SID
        var room = socket.id.replace(/[^a-zA-Z0-9]/g, "");
        //return and tell the client its room
        socket.emit('sendRoomToClient', {
          room: room,
          users: numUsers
        }); // Because we are calling socket itself id as his room, and he will wait
      }

    });

該邏輯似乎在單核 myapp.js 上運行完美,如果我在簡單的 1 處理器中以 fork 模式運行它,但是當我在 NGNIX 負載均衡器模式下運行它時,如果他們來自不同的 IP,它不會連接 2 個用戶。 (或者我假設兩者都遇到了不同的過程。請參閱下面我不想要的場景,但現在正在發生這種情況,

  1. 用戶 A 使用進程(比如說 process-2)來到頁面,=> 它被添加到隊列中
  2. 用戶 B 使用進程(假設是進程 4)進入頁面,=> 它也被添加到隊列中,但實際上不應該,因為進程 2 中已經有 1 人在等待。 在完美的情況下,用戶 A 應該被彈出並連接到用戶 B。但是這里用戶 B 一直在等待。
    1. 如果用戶 C 來了,也繼續等待 state:(

如何在 myapp 的 process-1 到 process-6 的所有進程之間共享我的全局變量及其值?

我已經在使用 Redis,正如您在底部看到的https://socket.io/docs/using-multiple-nodes/但它只能將發出事件傳遞給其他進程,我如何共享我的隊列變量來維護它myapp的所有進程中的持久state和值?

理想情況下,我希望它像這樣工作:

  1. 用戶 A(第一個用戶)使用進程(比如說 process-5 或負載均衡器選擇的任何其他進程)來到頁面,=> 它被添加到隊列中
  2. 用戶 B(第二個用戶)使用進程(比如說 process-2 或任何其他進程)進入頁面,=> 用戶 A 被彈出並與該用戶 B 連接,因為用戶 A 已經在等待隨機連接到任何人。

我只希望 2 個用戶無論何時何地來到這個公共頁面都能連接在一起。 如果第 3 個出現,則一直等待 state(在隊列中),直到第 4 個出現,然后彈出第 3 個以連接到第 4 個,依此類推。 但現在我的變量 Queue 似乎是 6 個 myapp 進程中的唯一變量。

我正在使用 Redis 像這樣:

var app = express();
if (process.env.ENV == "development") {

  var server = require("http").createServer(app);
} else {
  // Setting up a HTTPS Server

  var server = require("https").createServer(,
    app // i have removed configs for https.
  );

}
var io = require('socket.io');
var redis = require("socket.io-redis");
io.adapter(redis({
  host: "localhost",
  port: 6379
}));
server.listen(port, function () {
  console.log("Server listening at port %d", port);
});

io.attach(server);

接着



io.sockets
  .on('connection', socketioJwt.authorize({
    hash: jwt,
    timeout: 15000 // 15 seconds to send the authentication message
  })).on('authenticated', function (socket) {
//all socket io events go here
});

我不確定在 Redis 中存儲和檢索變量隊列的值/數組值的語法是什么。

這種情況也是我的問題,.. 我還沒有回答這個問題,但是.. 可能你可以將變量臨時用戶切換到在負載平衡開啟時具有復制的數據庫.. 使用 Redis 是這種情況下最好的一種..

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM