首页 > 解决方案 > 带有 mern 堆栈的 Socket io 使用 100% 的 CPU 功率

问题描述

我从我的主管那里得到了一个任务,要创建一个具有基本套接字 io 功能的程序,但我对此一无所知,所以我学会了它,这对我来说似乎很容易。在我的计算机程序上运行良好,但是在我将程序安装在生产服务器上后,当事件从前端发送到使用 React 编写的套接字 io 时,它使用了 100% 的 CPU。

这是我的套接字服务器。

const mongoose = require("mongoose");
const prevNum = require("./models/prevNums");
const Score = require("./models/scores");

const dotenv = require("dotenv");
const Config = require("./models/configs");
const Graphic = require("./models/graphic");
const Ip = require("./models/ips");

dotenv.config();
const mongoDB = process.env.MONGO_DB;

const io = require("socket.io")(9090, {
  cors: {
    origin: "*",
    methods: ["GET", "POST"],
    credentials: true,
  },
});

const axios = require("axios");
const appName = "tennis_socket_server";

// function console.log(log, options) {
//     if (options) {
//         options.forEach(opt => {
//             log += JSON.stringify(opt);
//         })
//     } else {
//         log = JSON.stringify(log)
//     }
//     console.log(log);
//     axios.post('http://192.168.2.202:9099/log', { app: appName, log })
// }

mongoose
  .connect(mongoDB, { useNewUrlParser: true, useUnifiedTopology: true })
  .then(() => {
    console.log("Mongoose is connected for socket server!!!");
  })
  .catch((err) => console.log(err));

function deletePrev(reverse) {
  prevNum.find({}).then((data) => {
    if (reverse) {
      prevNum.deleteOne(data[data.length - 1], (a, b) => {});
    } else {
      if (data.length >= 50) {
        prevNum.deleteOne(data[0], (a, b) => {});
      }
    }
  });
}

function filterState(state) {
  return {
    player1: state.player1,
    player2: state.player2,
    wonGames1: state.wonGames1,
    wonGames2: state.wonGames2,
    lastSet: state.lastSet,
    doNotReverse: state.doNotReverse,
    reverseInLastSet: state.reverseInLastSet,
    names: state.names,
    tourID: state.tourID,
  };
}

function getSets(callback) {
  console.log("getSets");
  Score.find({}).then((data) => {
    let sets = [];

    data.forEach((e) => {
      if (
        e.checked !== true &&
        (e.finished === true ||
          (e.finishedGame === true && (e.wonGames1 === 5 || e.wonGames2 === 5)))
      ) {
        sets.push(e);
      }
    });

    io.emit("setSets", sets);
  });
}

io.on("connection", (socket) => {
  console.log("New device connected to socket server at 9090", [
    socket.handshake.address,
  ]);

  // socket.on('disconnect', () => {
  //     console.log('Device disconnected from socket server at 9090', [socket.handshake.address]);

  //     Ip.find({ip:socket.handshake.address})
  //     .then(data => {
  //         if(data.length > 0){
  //             Ip.deleteOne(data[0], (msg, err) => {
  //                 console.log("delete", err)
  //                 Ip.find({ })
  //                 .then(data => {
  //                     io.emit('setIps', data);
  //                 })
  //             })
  //         }
  //     })
  // })

  // Ip.find({})
  //     .then(data => {
  //         io.emit('setIps', data);
  //     })

  Score.find({}).then((data) => {
    Config.find({}).then((config) => {
      if (data[data.length - 1]) {
        let datum = new Object(data[data.length - 1]);
        datum = { ...datum };
        datum = datum._doc;
        let conif = {};
        if (config.length > 0) {
          conif = new Object(config[config.length - 1]);
          conif = { ...conif };
          conif = conif._doc;
        }
        io.emit("setScores", { ...datum, ...conif });
      } else {
        let newScore = new Score({
          player1: 0,
          player2: 0,
          wonGames2: 0,
          wonGames1: 0,
        });

        newScore.save().then(() => {
          if (config.length === 0) {
            let newConfigs = new Config({
              neededSetsToWin: 11,
              neededGamesToWin: 5,
              block: false,
              delay: true,
            });

            newConfigs.save().then(() => {
              io.emit("setScores", {
                neededSetsToWin: 11,
                neededGamesToWin: 5,
                player1: 0,
                player2: 0,
                wonGames2: 0,
                wonGames1: 0,
              });
            });
          } else {
            io.emit("setScores", {
              player1: 0,
              player2: 0,
              wonGames2: 0,
              wonGames1: 0,
            });
          }
        });
      }
    });
  });

  // socket.on('writeMyIP', () => {
  //     let newIP = new Ip({ip:socket.handshake.address});
  //     newIP.save()
  //     .then(() => {
  //         Ip.find({ })
  //         .then(data => {
  //             io.emit('setIps', data);
  //         })
  //     })
  // })

  socket.on("newSet", (scores) => {
    console.log("new set");
    Score.find({}).then((data) => {
      let newPrevDocument = new prevNum({
        ...filterState(data[data.length - 1]),
      });
      newPrevDocument.save().then(() => {
        deletePrev();
        let newDocument = {
          wonGames1: scores.wonGames1,
          wonGames2: scores.wonGames2,
          finished: true,
          time: new Date(),
          checked: false,
        };
        Score.updateOne(data[data.length - 1], newDocument, (a, b) => {}).then(
          () => {
            let oldScoreDocument = new Score({
              ...scores,
              player1: 0,
              player2: 0,
              finished: false,
              time: new Date(),
              tourID: data[data.length - 1].tourID,
            });
            oldScoreDocument.save().then(() => {
              io.emit("setScores", {
                ...scores,
                player1: 0,
                player2: 0,
                tourID: data[data.length - 1].tourID,
              });
              getSets();
            });
          }
        );
      });
    });
  });

  socket.on("finishGame", () => {
    console.log("finish game");

    Score.find({}).then((data) => {
      Score.updateOne(
        data[data.length - 1],
        { finishedGame: true, time: new Date() },
        (a, b) => {
          getSets();
        }
      );
    });
    prevNum.remove({}, (a, b) => {});
  });

  socket.on("newGame", () => {
    console.log("newGame");
    let newScoreDocument = new Score({
      player1: 0,
      player2: 0,
      wonGames1: 0,
      wonGames2: 0,
      startTime: new Date(),
    });
    newScoreDocument.save().then(() => {
      io.emit("setScores", {
        player1: 0,
        player2: 0,
        wonGames1: 0,
        wonGames2: 0,
        gonnaWin: {},
        lastSet: false,
        doNotReverse: false,
        reverseInLastSet: false,
      });
      Score.find({}).then((data) => {
        Score.updateOne(data[data.length - 1], { started: true }, (msg, err) =>
          console.log(msg, err)
        ).then(() => {
          let newTourID = data[data.length - 2].tourID;

          if (
            newTourID[newTourID.length - 2] +
              newTourID[newTourID.length - 1] ===
            "30"
          ) {
            newTourID = newTourID.slice(0, -3);

            let newTour = parseInt(newTourID[newTourID.length - 1], 10) + 1;

            if (newTour - 3 > 0) {
              newTour -= 3;
              let d = new Date(newTourID.slice(0, -2));
              d.setDate(d.getDate() + 1);

              d = d.toISOString().split("T")[0];

              newTourID = [d, newTour].join("-");
            } else {
              newTourID = newTourID.slice(0, -1);
              newTourID += newTour;
            }

            Graphic.find({ tourID: newTourID }).then((data) => {
              if (data.length > 0) {
                let newNames = data[0].graphic[0];

                let newTourIDWithGame = newTourID + "-1";
                io.emit("setScores", {
                  names: {
                    player1: newNames[0],
                    player2: newNames[1],
                    judge: newNames[2],
                  },
                  tourID: newTourIDWithGame,
                });
                getSets();
              } else {
                io.emit("setScores", {
                  names: {
                    player1: "Игрок 1",
                    player2: "Игрок 2",
                    judge: "Судья",
                  },
                  tourID: "",
                });
                getSets();
              }
            });
          } else {
            let lastGame = newTourID[newTourID.length - 1];
            newTourID = newTourID.slice(0, -1);

            if (newTourID[newTourID.length - 1] !== "-") {
              lastGame = newTourID[newTourID.length - 1] + lastGame;
              newTourID = newTourID.slice(0, -1);
            }

            newTourID = newTourID.slice(0, -1);

            Graphic.find({ tourID: newTourID }).then((data) => {
              if (data.length > 0) {
                let newNames = data[0].graphic[parseInt(lastGame, 10)];

                let newTourIDWithGame =
                  newTourID + "-" + (parseInt(lastGame, 10) + 1);
                io.emit("setScores", {
                  names: {
                    player1: newNames[0],
                    player2: newNames[1],
                    judge: newNames[2],
                  },
                  tourID: newTourIDWithGame,
                });
                getSets();
              } else {
                io.emit("setScores", {
                  names: {
                    player1: "Игрок 1",
                    player2: "Игрок 2",
                    judge: "Судья",
                  },
                  tourID: "",
                });
                getSets();
              }
            });
          }
        });
      });
    });
  });

  socket.on("undoScores", (changeSet) => {
    prevNum.find({}).then((data) => {
      Score.find({}).then((scoreData) => {
        let scores = data[data.length - 1];
        let newScore = filterState(scores);
        let prevScore = scoreData[scoreData.length - 1];

        console.log("undo");
        if (prevScore) {
          prevScore = filterState(prevScore);
          if (
            prevScore.player1 === newScore.player1 &&
            prevScore.player2 === newScore.player2 &&
            prevScore.wonGames1 === newScore.wonGames1 &&
            prevScore.wonGames2 === newScore.wonGames2
          ) {
            Score.deleteOne(scoreData[scoreData.length - 1], (a, b) =>
              console.log(a, b)
            ).then(() => {
              Score.updateOne(scoreData[scoreData.length - 2], {
                finished: false,
                finsihedGame: false,
                started: false,
              }).then(() => {
                io.emit("setScores", newScore);
                deletePrev(true);
              });
            });
          } else if (
            prevScore.wonGames1 !== newScore.wonGames1 ||
            prevScore.wonGames2 !== newScore.wonGames2
          ) {
            if (changeSet) {
              Score.deleteOne(scoreData[scoreData.length - 1], (a, b) =>
                console.log(a, b)
              ).then(() => {
                Score.updateOne(scoreData[scoreData.length - 2], {
                  finished: false,
                  ...newScore,
                }).then(() => {
                  io.emit("setScores", { ...newScore, changeSet: false });
                  deletePrev(true);
                  getSets();
                });
              });
            } else {
              io.emit("setScores", { changeSet: true });
            }
          } else {
            Score.updateOne(scoreData[scoreData.length - 1], newScore).then(
              () => {
                io.emit("setScores", newScore);
                deletePrev(true);
              }
            );
          }
        } else {
          Score.updateOne(scoreData[scoreData.length - 1], newScore).then(
            () => {
              io.emit("setScores", newScore);
              deletePrev(true);
            }
          );
        }
      });
    });
  });

  socket.on("help", () => {
    io.emit("help");
  });

  socket.on("refresh", () => {
    io.emit("refresh");
  });

  socket.on("scoreUpdate", (scores) => {
    console.log("scoreUpdate", [scores]);

    // console.log(scores);

    Score.find({}).then((data) => {
      if (data[data.length - 1]) {
        if (!data[data.length - 1].finished) {
          deletePrev();

          let datum = data[data.length - 1];
          let newPrevs = {
            player1: datum.player1,
            player2: datum.player2,
            wonGames1: datum.wonGames1,
            wonGames2: datum.wonGames2,
            doNotReverse: datum.doNotReverse,
            lastSet: datum.lastSet,
            reverseInLastSet: datum.reverseInLastSet,
            names: datum.names,
            tourID: datum.tourID,
          };

          console.log(scores);

          let prevNumDocument = new prevNum(newPrevs);

          prevNumDocument.save().then(() => {
            Score.updateOne(data[data.length - 1], scores).then(() => {
              io.emit("setScores", scores);
            });
          });
        }
      } else {
        let newScoreDocument = new Score({ ...scores, time: new Date() });

        newScoreDocument.save().then(() => {
          io.emit("setScores", scores);
        });
      }
    });
  });

  socket.on("setTourID", (info) => {
    let tourID = [info.date, info.tour, info.game].join("-");
    let tourIDNoGame = [info.date, info.tour].join("-");

    Score.find({}).then((scores) => {
      Graphic.find({ tourID: tourIDNoGame }).then((data) => {
        if (data.length > 0) {
          let player1 = data[0].graphic[info.game - 1][0];
          let player2 = data[0].graphic[info.game - 1][1];
          let judge = data[0].graphic[info.game - 1][2];
          Score.updateOne(
            scores[scores.length - 1],
            { names: { player1, player2, judge }, tourID },
            (msg, err) => {
              console.log(msg, err);
              io.emit("setScores", {
                names: { player1, player2, judge },
                tourID,
              });
            }
          );
        }
      });
    });
  });

  socket.on("warn", (text) => {
    io.emit("warn", text);
  });

  socket.on("getSets", (callback) => getSets(callback));

  socket.on("saveSet", (res) => {
    let s = res.set;
    console.log("saveSet");
    Score.find({ _id: s._id }).then((data) => {
      Score.updateOne(
        data[data.length - 1],
        { ...s, modified: true },
        (msg, err) => {
          getSets();
          console.log(msg, err);
        }
      );
    });
  });
});

我从前端发送socket.emit('name', {a small object as argument});

我没有将我的程序设置为生产模式,但我认为它不会发挥重要作用,因为同时连接到我的服务器的设备不超过 10 个。

我想socket io使用更少的CPU。

标签: reactjssocketswebsocketsocket.iomern

解决方案


推荐阅读