Как совместно использовать глобальную переменную в мультикластерном режиме узла js, когда сокет io работает на балансировщике нагрузки NGNIX, но на разветвлении с использованием pm2? - PullRequest
0 голосов
/ 17 октября 2019

У меня есть приложение Socket IO, работающее с использованием балансировки нагрузки NGNIX, и мое приложение работает на 6 ядрах, и нагрузка распределяется между ними. Когда я делаю pm2 list myapp, он показывает, что работает в режиме ветвления, но охватывает 6 процессов, из-за балансировки нагрузки nginx



 │ 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, и она хранит пользователей, когда они приходят на страницу и ожидают соединения с другим человеком. Когда приходит другой человек, старый человек выталкивается из очереди, и у них обоих общий идентификатор, чтобы общаться вместе. я использую 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
        }); //coz we r calling socket itself id as his room, and he will wait
      }

    });

Логика, кажется, прекрасно работает на одноядерном myapp.js, если я запускаю его в forkрежим в простом 1 процессоре, но когда я запускаю его в режиме балансировки нагрузки NGNIX, он не соединяет 2 пользователей, если они приходят с разных IP-адресов. (или я предполагаю, что если оба попадут в другой процесс. См. сценарий ниже, который я не хочу, но это происходит сейчас,

  1. Пользователь A приходит на страницу, используя процесс (скажем, процесс-2), => он добавляется в очередь
  2. Пользователь B заходит на страницу с помощью процесса (скажем, process-4), => он также добавляется в очередь, но на самом деле это не должно, потому что в процессе 2 уже ждут 1 человек. В идеальном случае, пользователь А должен быть подключен и подключен к пользователю Б. Но здесь пользователь Б продолжает ждать.
  3. Если пользователь C приходит, он также переходит в состояние ожидания: (

Как передать мою глобальную переменную и ее значения всем процессам myapp, которые обрабатываются-1 к процессу-6?

Я уже использую Redis, как вы можете видеть здесь внизу https://socket.io/docs/using-multiple-nodes/, но он может только передавать события emit другим процессам, как я могу поделиться своей переменной очередичтобы сохранить его постоянное состояние и значения среди всех процессов myapp? Так что если

В идеале я хочу, чтобы он работал так:

  1. Пользователь A (первыйпользователь) приходит на страницу, используя процесс (скажем, процесс-5 или любой другой процесс по выбору балансировщика нагрузки), => он добавляется в очередь
  2. Пользователь Б (второй пользователь) приходит на страницу, используя процесс(скажем, процесс-2 или любой другой процесс), => Пользователь A подключен и подключен к этому пользователю B, потому что пользователь A уже ожидал случайного подключения к кому-либо.

Я просто хочу 2пользователи должны быть связаны друг с другом, когда и какэ, они приходят на эту общую страницу. и если 3-й приходит, он остается в состоянии ожидания (в очереди) до 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
});

Я не уверен, каков синтаксис для хранения и восстановления значений / значений массива переменной Queue в redis. Могу ли я получить помощь, пожалуйста?

...