首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当socket io在NGNIX负载均衡器上运行,但在使用pm2的叉子上运行时,如何在节点js多集群模式下共享全局变量?

当socket io在NGNIX负载均衡器上运行,但在使用pm2的叉子上运行时,如何在节点js多集群模式下共享全局变量?
EN

Stack Overflow用户
提问于 2019-10-17 13:43:56
回答 1查看 982关注 0票数 0

我有一个socket应用程序运行使用NGNIX负载平衡和我的应用程序运行在6个核心和负载是分布在其中。当我执行pm2 list myapp时,它显示它运行在叉模式下,但跨越6个进程,这是由于nginx负载平衡的缘故。

代码语言:javascript
复制
│ 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文件的示例

代码语言:javascript
复制
# 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作为房间。

样本代码

代码语言:javascript
复制
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处理器中以叉子模式运行它,但是当我在NGNIX负载均衡器模式下运行它时,如果用户来自不同的IP,它就不会连接到两个用户。)或者我假设如果两者都有不同的过程。下面是我不想看到的情况,但现在已经发生了,

  1. 用户A使用process (例如process-2)进入页面,=>是添加到队列中的
  2. 用户B使用进程(例如process-4)到达页面,=>也添加到队列中,但它实际上不应该,因为进程中已经有1人在等待-2。在完美的情况下,用户A应该被弹出并连接到用户B。但是在这里,用户B一直在等待。如果用户C来了,它也将继续等待状态:(

如何在进程-1到进程-6的所有进程之间共享我的全局变量及其值?

我已经在使用Redis了,您可以在下面看到https://socket.io/docs/using-multiple-nodes/,但它只能将发射事件传递给其他进程,我如何在myapp的所有进程之间共享队列变量以维护其持久状态和值?

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

  1. 用户A(第一个用户)使用进程(假设process-5或负载平衡器选择的任何其他进程)进入页面,=>它被添加到队列中,
  2. 用户B(第二个用户)使用进程(例如process-2或任何其他进程)进入页面,=>用户A被弹出并与此用户B连接,因为用户A已经在等待随机连接到任何人。

我只想让两个用户连接在一起,无论何时,无论他们来到这个共同的页面。如果第三次到来,它会一直处于等待状态(排队),直到第四次到来,然后第三次被弹出连接到第四次,依此类推。但是现在,我的变量队列在6个myapp进程中似乎是唯一的变量。

我使用Redis是这样的:

代码语言:javascript
复制
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);

然后

代码语言:javascript
复制
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中存储和检索变量队列的值/数组值的语法是什么。

EN

回答 1

Stack Overflow用户

发布于 2022-05-19 07:56:17

这个案子也是我的问题.我没有回答这个问题,但是..。可能是,您可以将变量临时用户切换到在负载平衡打开时具有复制功能的数据库。在这种情况下使用Redis是最好的之一。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58434139

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档