Javascript 当socket io在NGNIX负载平衡器上运行,但在使用pm2的fork上运行时,如何在node js多集群模式下共享全局变量?

Javascript 当socket io在NGNIX负载平衡器上运行,但在使用pm2的fork上运行时,如何在node js多集群模式下共享全局变量?,javascript,node.js,nginx,socket.io,pm2,Javascript,Node.js,Nginx,Socket.io,Pm2,我有一个socket io应用程序正在使用NGNIX负载平衡运行,我的应用程序运行在6个内核上,负载分布在这些内核之间。当我执行pm2 list myapp时,它显示它在fork模式下运行,但由于nginx负载平衡,它跨越了6个进程 │ myapp-1 │ 21 │ fork │ │ myapp-2 │ 45 │ fork │ │ myapp-3 │ 32 │ fork │ │ myapp-4 │ 11 │ fork │

我有一个socket io应用程序正在使用NGNIX负载平衡运行,我的应用程序运行在6个内核上,负载分布在这些内核之间。当我执行pm2 list myapp时,它显示它在fork模式下运行,但由于nginx负载平衡,它跨越了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上,如果我在simple 1处理器中以fork模式运行它,逻辑似乎工作得非常完美,但是当我在NGNIX负载平衡器模式下运行它时,如果两个用户来自不同的IP,它就无法连接到他们。(或者我假设两者都在不同的过程中发生。请参阅下面的场景,我不想看到,但现在正在发生这种情况

  • 用户A使用process(比如process-2)进入页面,=>it 已添加到队列中
  • 用户B使用process(比如process-4)进入页面,=>it 也被添加到队列中,但实际上不应该,因为 在流程2中已经有1个人在等待。在理想情况下,用户A应该弹出并连接到用户B。但在这里,用户B一直在等待。
  • 如果用户C出现,它也处于等待状态:(
  • 如何在myapp中process-1到process-6的所有进程之间共享全局变量及其值

    我已经在使用Redis了,正如您在底部看到的,但它只能将emit事件传递给其他进程,我如何在myapp的所有进程中共享队列变量以保持其持久状态和值

    理想情况下,我希望它能像这样工作:

  • 用户A(第一个用户)使用process(比如process-5或负载平衡器选择的任何其他进程)来到页面,=>它被添加到队列中
  • 用户B(第二个用户)使用进程(比如进程2或任何其他进程)进入页面,=>弹出用户A并与该用户B连接,因为用户A已经在等待随机连接到任何人
  • 我只想让两个用户无论何时何地来到这个公共页面都连接在一起。如果第三个用户来了,它会一直处于等待状态(在队列中),直到第四个用户来了,然后第三个用户弹出连接到第四个用户,依此类推。但现在我的变量队列似乎是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
    或其他东西,以便所有进程共享相同的
    队列
    。您提到您已经在使用
    Redis
    ,但我在你的代码中看不到。不过,你的
    队列应该在
    redis
    中读/写。想想看
    redis
    是你的全局数据库。@Raul是的,我在使用redis,我已经用我正在使用的redis代码更新了我的问题。它只是像在这个redislin上建议的那样围绕着套接字io适配器socket io文档的k。所以我不是100%确定redis我在这个例子中使用redis。你能告诉我在redis中存储和检索全局变量
    Queue
    的语法,而不是像我现在这样在我的普通myapp.js文件中作为全局变量。我如何在redis中存储和获取变量数据?如果我没有错,你会怎么做当前正在使用redis的只是socket.io通信部分。但是,当有人加入您的页面时,您可以查看
    队列
    对象,该对象在脚本中是全局的,但对每个实例都是局部的。因此,我想您所要做的就是读取和写入一个中心redis实例。看看示例,可能会帮助您开始。@Raul i am alr我已经在代码中使用socket.io-redis模块了,所以我需要这个
    require('redis'))
    模块?请查看上面的代码,并让我知道如何在socket io存储中存储我的
    队列
    变量。我正在尝试按照此处的指南操作,但它不起作用。如果您能在下面给我代码示例,用redis store and store配置我的socket io,并获取我的
    队列变量
    ,我会给您最好的答案。我很抱歉我不是Redis的专家