NodeJS和Mongo线谁上线

MrP*_*PHP 5 mongodb node.js

TL; 博士

记录在线用户并报告计数(基于 mongo find)


我们为学校和学生提供了一个 saas 应用程序,作为其中的一部分,我一直想要一个在线自动收报机的“直播”。

学校的老师会看到计数器,学生和家长会触发它。

我有一个 socket.io 从 web 应用程序连接到 NodeJS 应用程序。在有大量流量的地方,Node/Mongo 服务器无法处理它,与其投入更多资源,我认为最好优化代码 - 因为我不知道我在做什么:D

随着每个学生页面加载:使用以下对象创建一个 socket.io 连接:

{
'name': 'student or caregiver name',
'studentID': 123456,
'schoolID': 123,
'role': 'student', // ( or 'mother' or 'father' )
'page': window.location
}
Run Code Online (Sandbox Code Playgroud)

在我的节点脚本中:

io.on('connection', function(client) {
    // if it's a student connection.. 
    if(client.handshake.query.studentID) {
        let student = client.handshake.query; // that student object
            student.online = new Date();
            student.offline = null;
        db.collection('students').updateOne({ 
           "reference": student.schoolID + student.studentID + student.role }, { $set: student 
        }, { upsert: true });


    }

    // IF STAFF::: just show count!
    if(client.handshake.query.staffID) {
      db.collection('students').find({ 'offline': null, 'schoolID':client.handshake.query.schoolID }).count(function(err, students_connected) {
          
          emit('online_users' students_connected);
       });
    }



    client.on('disconnect', function() {
        // then if the students leaves the page..
        if(client.handshake.query.studentID) {
            db.collection('students').updateMany({ "reference": student.reference }, { $set: { "offline": new Date().getTime() } })
            .catch(function(er) {});
         }

         // IF STAFF::: just show updated count!
         if(client.handshake.query.staffID) {
           db.collection('students').find({ 'offline': null, 'schoolID':client.handshake.query.schoolID }).count(function(err, students_connected) {
          
                emit('online_users' students_connected);
            });
         }
     });
});


Run Code Online (Sandbox Code Playgroud)

您会添加哪些 Mongo 索引,您是否会以不同的方式(并在不同的集合中)存储在线学生到像这样的“页面跟踪”类型的交易?(这会记录页面和持续时间,所以我稍后有另一个调用来提取它 - 但这并没有被大量使用或导致问题。

如果分开,然后插入,然后删除?

EMIT() 给员工用户,我如何只向与学生具有相同学校 ID 的员工发送?

谢谢!

Mat*_*ttM 1

This won't be a complete answer without discussing the problem some more, but figured I'd post some general suggestions.

First, we should figure out where the performance bottlenecks are. Is it a particular query? Is it too many simultaneous connections to MongoDB? Is it even just too much round trip time per query (if the two servers aren't within the same data center)? There's quite a bit to narrow down here. How many documents are in the collection? How much RAM does the MongoDB server have access to? This will give us an idea of whether you should be having scaling issues at this point. I can edit my answer later once we have more information about the problem.

Based on what we know currently, without making any model changes, you could consider indexing the reference field in order to make the upsert call faster (if that's the bottleneck). That could look something like:

db.collection('students').createIndex({
  "reference": 1
},
{ background: true });
Run Code Online (Sandbox Code Playgroud)

If the querying is the bottleneck, you could create an index like:

db.collection('students').createIndex({
  "schoolID": 1
},
{ background: true });
Run Code Online (Sandbox Code Playgroud)

I'm not confident (without knowing more about the data) that including offline in the index would help, because optimizing for "not null" can be tricky. Depending on the data, that may lead to storing the data differently (like you suggested).