【问题标题】:Node.js application starts never ending processes in productionNode.js 应用程序在生产中启动永无止境的流程
【发布时间】:2021-04-23 15:20:00
【问题描述】:

我在 cPanel 上托管一个 node.js 应用程序。它只不过是使用包含 CRUD 的 express 的简单 RESTful Web API。我面临的问题是进程的数量随着时间的推移而增加,这意味着以前的一些进程永远不会结束,应用程序会不断添加,直到我的服务器达到资源限制并且所有应用程序停止工作。

cPanel 实际上没有办法console.log() 我在应用程序内部编写代码要执行的任何错误。我所能看到的只是流程产生的主要域。

我尝试为此编写自己的日志文件,但这也无济于事

我在我的终端中写这个来检查进程ps -ef | grep node(因为我知道所有的进程都只是 node.js 进程)。我注意到我可以在此命令中看到的进程数量与我在 cPanel 仪表板中看到的不同(少得多)!

更新:

例如,这是造成问题的 API 之一:

我的app.js(入口点)

require("dotenv").config();
const fs = require("fs");
const path = require("path");
const express = require("express");
const bodyParser = require("body-parser");
const morgan = require("morgan");
const cors = require("cors");

const mongoose = require("mongoose");

// Initialize the app
const app = express();

// Enable CORS
app.use(cors({ origin: true }));
 
// create a write stream (in append mode)
var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' })
 
// setup the logger
app.use(morgan('combined', { stream: accessLogStream }))

// Parse the body to JSON
app.use(bodyParser.json());

// Serving static files
app.use("/images", express.static("images"));

// Routes middlewares go here!
app.use("/api/categories", require("./routes/category-routes"));
app.use("/api/users", require("./routes/user-routes"));
app.use("/api/sellers", require("./routes/seller-routes"));
app.use("/api/services", require("./routes/service-routes"));
app.use("/api/resellers", require("./routes/reseller-routes"));
app.use("/api/support", require("./routes/support-routes"));
app.use("/api/trackings", require("./routes/tracking-routes"));

app.use((err, req, res, next) => {
  console.log(err);
  res
    .status(500)
    .send({ success: false, error: err, errors: ["Something went wrong"] });
});

// Start listening finally
const port = process.env.PORT || 5000;

mongoose
  .connect(process.env.MONGO_URI, {
    // .connect(process.env.MONGO_URI_NAI_NAI_NAI, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useFindAndModify: false,
  })
  .then(() => {
    app.listen(() => {
      console.log(`Server started on port ${port}`);
    });
  })
  .catch((err) => {
    try {
      fs.appendFileSync("my-own-log-file.txt", `\n\n${err}`);
    } catch (err) {
      console.log(err);
    }
    process.exit(1)
    console.log(err);
  });

我在这里注册路线:

// @route   POST /api/services/filtered-by-state
// @desc    To fetch all services filtered by state
// @access  public

router.post(
  "/filtered-by-state/",
  body("state")
    .trim()
    .not()
    .isEmpty()
    .withMessage("Please enter choose a state"),
  checkValidity,
  serviceControllers.getServicesFilteredByState
);

这是控制器:

exports.getServicesFilteredByState = (req, res) => {
  let page = req.query.page || 1;
  const { state, sellerId } = req.body;
  let options = {};

  if (page) {
    page = parseInt(page);
  }

  if (state === "Australia Wide") {
    options = { state }; // Look for only documents where state is 'Australia wide'
  } else {
    // Look for documents where state is 'Australia wide' or ```state``` itself
    options = { state: { $in: ["Australia Wide", state] } };
  }

  if (!sellerId) {
    options.isHidden = false;
  }

  let totalItems = 0;

  Service.find(options)
    .countDocuments()
    .then((numServices) => {
      totalItems = numServices;
      return Service.find(options)
        .sort("sortingOrder")
        .populate("sellerId")
        .populate("categoryId");
      // .skip((page - 1) * ITEMS_PER_PAGE)
      // .limit(ITEMS_PER_PAGE);
    })
    .then((foundServices) => {
      res.status(200).json({
        success: true,
        totalItems,
        services: foundServices,
      });
    })
    .catch((err) => {
      console.log(err);
      res.status(500).status("Something went wrong");
    });
};

这是简单的 CRUD!

【问题讨论】:

  • 您是否尝试过使用例如 pm2 运行应用程序?它会自动写入一个可能对您有帮助的日志
  • 感谢您的建议,我实际上使用 pm2 启动了我的应用程序,但我不知道在哪里可以检查此特定应用程序有多少进程。它向我展示了一些基本的东西,比如 cpu mem 使用和正常运行时间等,你能帮我看看我的应用程序的进程数吗?
  • 我不确定我是否了解数字进程是如何准确增加的。是他们在重新启动期间没有被杀死还是只是随机产生?我的期望是,一个简单的 RESTful API 在启动后不应该真正产生任何新进程。
  • @TayyabFerozi 能否分享一下你创建的进程和增加的进程的截图
  • @aRvi 当我向他们的支持团队询问他们如何定义 number of processes 时,他们回答说:“进程是您的计算机进行的计算,因此进程数将是您的计算机可以进行的计算数同时制作”。这里是你想要的图片:imgur.com/a/4xQp5AB

标签: node.js express hosting cpanel web-hosting


【解决方案1】:

Node.js 应用程序在单线程上运行,并且事件循环也在同一线程上运行。所以我们可以说 Node.js 是单线程的,但问题是 Node.js 中有一些库不是单线程的。

Node.js 内部使用 libuv 库,该库负责处理与操作系统相关的任务,如基于异步 I/O 的操作系统、网络、并发等。 Libuv 建立了一个由 x 个线程组成的线程池,通过利用所有 CPU 内核的能力来执行与操作系统相关的操作。例如,如果您有一台具有 4 个 CPU 内核的计算机,Libuv 将创建一个由 4 个线程组成的线程池,池中的每个线程都分配给每个内核。这导致每个内核一个线程。

但是,您可以通过更改 UV_THREADPOOL_SIZE 环境变量来更改此值:

process.env.UV_THREADPOOL_SIZE = numOfThreads;

如果您没有对代码做任何奇怪的事情,这对于 Node.js 来说是完全正常的,并且会使用尽可能多的 CPU 内核来获得更好的性能。

我发现了一篇非常有趣的文章,它详细解释了所有内容: Is Node.js Really Single-Threaded?

【讨论】:

  • 说实话,我不认为 OP 在他的问题中意味着线程。
  • 实际上我无法了解我的服务器中实际发生的情况。如果这是这些线程的问题,则应在异步任务完成时自动完成进程。为什么它会一直运行下去?如果您知道可能发生的情况,请告诉我。如果我的问题得到解决,我一定会再次开始赏金以奖励回答者,谢谢您的回答
  • 没有任何代码或任何脚本,我们可以在启动进程时查看您是否做错了什么,我们无能为力。我找到了一个 cpanel 问题论坛,您可能会在其中找到答案,或者至少可以更清楚地说明问题所在:forums.cpanel.net/threads/entry-process.667557
猜你喜欢
  • 2013-03-06
  • 2011-10-25
  • 1970-01-01
  • 2015-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-05
相关资源
最近更新 更多