1. 首页
  2. Nodejs

也许,你永远都不应该直接在生产环境中运行 Node.js

有时我想知道我是否一无所知。

就在几周前,我正在和一个朋友聊天,后者提到了“您永远不会在生产环境中直接针对Node运行应用程序”。我大力点头表示我永远不会在生产中与Node发生冲突,因为……哈哈哈……大家都知道。但是我不知道!我应该知道吗?我仍然可以参加程序吗?

如果我要绘制一个维恩图,说明我所知道的vs其他人都知道的感觉,它将看起来像这样……

也许,你永远都不应该直接在生产环境中运行 Node.js

顺便说一下,这个小点随着我年龄的增长而变小。

刘慧卿(Alicia Liu)创建的更好的图表改变了我的生活。她说这更像是……

也许,你永远都不应该直接在生产环境中运行 Node.js

我非常喜欢这个图,因为我希望它是真实的。我不想把我的余生都花在一个微小的,逐渐缩小的无意义的蓝点上。

如此戏剧性。怪潘多拉。在撰写本文时,我无法控制接下来要播放的内容,而Dashboard Confessional就是一种毒品。

好吧,假设Alicia的图表是正确的,我想与大家分享我现在对在生产环境中运行Node应用程序的了解。也许我们相对的维恩图在这个问题上并不重叠。

首先,让我们解决“永远不要在生产环境中直接针对Node运行应用程序”这一说法。

切勿在生产中直接针对Node运行

也许。但也许不是。让我们讨论一下此语句背后的原因。首先,让我们看看为什么不这样做。

假设我们有一台简单的Express服务器。我能想到的最简单的Express服务器…

const express = require("express");
const app = express();
const port = process.env.PORT || 3000;

// viewed at http://localhost:3000
app.get("/", function(req, res) {
  res.send("Again I Go Unnoticed");
});

app.listen(port, () => console.log(`Example app listening on port ${port}!`));

我们将使用package.json文件中的启动脚本来运行它。

"scripts": {
  "dev": "npx supervisor index.js",
  "start": "node index.js"
}

也许,你永远都不应该直接在生产环境中运行 Node.js

这里有两个问题。第一个是发展问题,第二个是生产问题。

开发的问题是,当我们更改代码时,我们必须停止并启动应用程序以获取我们的更改。

为了解决这个问题,我们通常使用某种Node进程管理器,例如supervisornodemon。每当我们进行更改时,这些软件包将监视我们的项目并重新启动服务器。我通常这样做

"scripts": {  "dev": "npx supervisor index.js",  "start": "node index.js"}

然后我跑npm run dev。请注意,我在npx supervisor这里运行,这使我supervisor无需安装即可使用软件包。我❤️2019.主要是。

我们的另一个问题是我们仍然直接针对Node运行,我们已经说过这很糟糕,现在我们将找出原因。

我将在此处添加另一条尝试从不存在的磁盘读取文件的路由。这是一个错误,很容易在任何实际应用程序中出现。

const express = require("express");
const app = express();
const fs = require("fs");
const port = process.env.PORT || 3000;

// viewed at http://localhost:3000
app.get("/", function(req, res) {
  res.send("Again I Go Unnoticed");
});

app.get("/read", function(req, res) {
  // this does not exist
  fs.createReadStream("my-self-esteem.txt");
});

app.listen(port, () => console.log(`Example app listening on port ${port}!`));

如果直接使用Node对Node运行此操作npm start并导航到read 端点,则会收到错误消息,因为该文件不存在。

也许,你永远都不应该直接在生产环境中运行 Node.js

哪个-没什么大不了的吗?这是一个错误。它发生了。

没有。大事了 如果返回到终端,您将看到该应用程序已完全关闭。

Js中文网 – 前端进阶资源教程 www.javascriptC.com,typescript 中文手册
专注分享前端知识,你想要的,在这里都能找到

也许,你永远都不应该直接在生产环境中运行 Node.js

这意味着,如果您返回浏览器并尝试转到该站点的根URL,则会得到相同的错误页面。一种方法的一个错误使每个人都无法使用该应用程序。

那很糟。真的很糟糕。这是人们说“从不直接与生产中的Node对抗”的主要原因之一。

好。因此,如果我们不能在生产中与Node竞争,那么在生产中运行Node的正确方法是什么?

生产节点的选项

我们有一些选择。

其中之一就是简单地使用类似产品supervisornodemon在生产中使用的方式,就像在开发人员中使用它们的方式一样。可以,但是这些工具在轻量级方面有点不足。更好的选择是称为pm2的东西。

pm2救援

pm2是一个Node进程管理器,它有很多麻烦。就像其他所有“ JavaScript”一样,npm您可以从(全局)安装它,也可以npx再次使用。我不想告诉你如何过自己的生活。

有很多方法可以在pm2上运行您的应用程序。最简单的方法是仅调用pm2 start您的入口点。

"scripts": {
  "start": "pm2 start index.js",
  "dev": "npx supervisor index.js"
},

然后您会在终端中看到类似的内容……

也许,你永远都不应该直接在生产环境中运行 Node.js

那就是我们的过程在pm2监视下在后台运行。如果您访问read端点并使应用程序崩溃,则pm2将自动重新启动它。您不会在终端中看到任何内容,因为它在后台运行。如果您想观看pm2的工作,则必须运行pm2 log 0。该0是我们希望看到日志的进程的ID。

也许,你永远都不应该直接在生产环境中运行 Node.js

好了!您会看到pm2由于我们未处理的错误而在应用程序关闭时重新启动了它。

我们还可以拉出dev命令并为我们提供pm2监视文件,并在进行任何更改时重新启动。

"scripts": {
  "start": "pm2 start index.js --watch",
  "dev": "npx supervisor index.js"
},

请注意,因为pm2在后台运行,所以您不能仅仅ctrl+c退出正在运行的pm2进程。您必须通过传递ID或名称来停止它。

pm2 stop 0

pm2 stop index

另外,请注意pm2保留了对该过程的引用,因此您可以重新启动它。

也许,你永远都不应该直接在生产环境中运行 Node.js

如果要删除该流程引用,则需要运行pm2 delete。您可以使用来在一个命令中停止和删除进程delete

pm2 delete index

我们还可以使用pm2来运行应用程序的多个进程。pm2将自动在这些实例之间平衡负载。

pm2 fork模式下的多个进程

pm2具有大量的配置选项,这些选项包含在“生态系统”文件中。要创建一个,请运行pm2 init。你会得到这样的东西…

module.exports = {
  apps: [
    {
      name: "Express App",
      script: "index.js",
      instances: 4,
      autorestart: true,
      watch: true,
      max_memory_restart: "1G",
      env: {
        NODE_ENV: "development"
      },
      env_production: {
        NODE_ENV: "production"
      }
    }
  ]
};

我将忽略本文的“部署”部分,因为我不知道它的作用。

在“应用程序”部分中,您可以定义要让pm2运行和监视的应用程序。您可以运行多个。这些配置设置中有许多可能是不言自明的。我想在这里重点介绍的是实例设置。

pm2可以运行您的应用程序的多个实例。您可以传入许多要运行的实例,而pm2会增加很多实例。因此,如果我们要运行4个实例,我们可以拥有以下配置文件。

module.exports = {
  apps: [
    {
      name: "Express App",
      script: "index.js",
      instances: 4,
      autorestart: true,
      watch: true,
      max_memory_restart: "1G",
      env: {
        NODE_ENV: "development"
      },
      env_production: {
        NODE_ENV: "production"
      }
    }
  ]
};

然后我们用运行它pm2 start

也许,你永远都不应该直接在生产环境中运行 Node.js

pm2现在以“群集”模式运行。这些进程中的每个进程都在我计算机上的不同CPU上运行,具体取决于我拥有多少个内核。如果我们想为每个内核运行一个进程而又不知道我们有多少个内核,我们可以将max参数传递给instances值。

{
   ...
   instances: "max",
   ...
}

Js中文网 – 前端进阶资源教程 www.javascriptC.com,typescript 中文手册
专注分享前端知识,你想要的,在这里都能找到

让我们找出这台机器上有多少个内核。

也许,你永远都不应该直接在生产环境中运行 Node.js

8码!哇靠。我要在Microsoft发行的计算机上安装Subnautica。别跟他们说

在单独的CPU上运行进程的好处是,如果您有一个运行amok并占用100%CPU的进程,其他进程仍然可以运行。如果传递的实例数多于核心数,则pm2将在必要时使CPU上的进程加倍。

您可以使用pm2做更多的事情,包括监视和处理那些讨厌的环境变量

需要注意的另一项内容:如果由于某种原因希望pm2运行npm start脚本,则可以通过将npm作为进程并传递来实现-- start。在这里,“开始”之前的空间非常重要。

pm2 start npm -- start

Azure AppService中,默认情况下在后台包含pm2。如果要在Azure中使用pm2,则无需在package.json文件中包含它。您只需添加一个生态系统文件就可以了。

也许,你永远都不应该直接在生产环境中运行 Node.js

好!既然我们已经了解了pm2的全部知识,那么让我们谈谈为什么您可能不想使用它,并且直接针对Node运行确实可以。

直接在生产中针对Node运行

我对此有一些疑问,所以我联系了蒂尔尼·赛伦Tierney Cyren),他是庞大的橙色知识圈的一部分,尤其是在涉及Node时。

Tierney指出了使用基于节点的流程管理器(例如pm2)的一些缺点。

主要原因是您不应该使用Node来监视Node。您不想使用要监视的事物来监视该事物。这有点像您在星期五晚上要求我的十几岁的儿子监督自己:结局会很糟糕吗?可能会,也可能不会。但是您将发现困难的方法。

Tierney建议您不要让Node进程管理器完全运行您的应用程序。取而代之的是,在更高级别上监视某些应用程序的单独实例。例如,如果您有一个Kubernetes集群,并且您的应用程序在单独的容器上运行,则是理想的设置。然后,Kubernetes可以监视这些容器,如果其中任何一个发生故障,它可以将其带回并报告其健康状况。

在这种情况下,您可以直接在Node上运行,因为您需要进行更高级别的监视。

事实证明,Azure已经在这样做。如果我们不将pm2生态系统文件推送到Azure,它将使用我们的package.json文件启动脚本启动应用程序,我们可以直接在Node上运行。

"scripts": {
  "start": "node index.js"
}

在这种情况下,我们直接针对Node运行,没关系。如果应用程序崩溃了,您会注意到它又回来了。这是因为在Azure中,您的应用程序在容器中运行。Azure正在协调您的应用程序在其中运行的容器,并知道它何时面世。

也许,你永远都不应该直接在生产环境中运行 Node.js

但是您在这里仍然只有一个实例。崩溃后,该容器需要一秒钟才能恢复在线状态,这意味着您的用户可能会有几秒钟的停机时间。

理想情况下,您需要运行多个容器。解决方案是将应用程序的多个实例部署到多个Azure AppService站点,然后使用Azure Front Door在单个IP地址后面对应用程序进行负载平衡。前门将知道何时容器发生故障,并将流量路由到应用程序的其他正常实例。

Azure前门服务| Microsoft Azure 使用Azure前门交付,保护和跟踪全球分布式微服务应用程序的性能… azure.microsoft.com

Js中文网 – 前端进阶资源教程 www.javascriptC.com,typescript 中文手册
专注分享前端知识,你想要的,在这里都能找到

系统的

Tierney的另一个建议是使用来运行Node systemd。我不太了解(或一点也不了解)systemd,我已经把这个措辞弄乱了,所以让蒂尔尼用他自己的话说……

仅当您可以在部署中访问Linux并在服务级别上控制Node的启动方式时,此选项才可用。如果您在运行时间较长的Linux VM(例如Azure VM)中运行Node.js进程,那么您将是在systemd上运行Node.js的好地方。如果您只是将文件部署到诸如Azure AppService或Heroku之类的服务,或者在诸如Azure容器实例之类的容器化环境中运行,则应该避免使用此选项。

使用Systemd运行Node.js应用程序-第1部分 您已经在Node中编写了下一个出色的应用程序,并准备将其释放给全世界。这意味着您可以… nodesource.com

Node.js工作线程

Tierney还希望您知道Node中即将出现工作线程。这将使您可以在多个“工作者”(线程)上启动您的应用程序,从而不需要pm2之类的东西。也许。我不知道。我没有真正读过这篇文章。

Node.js v11.14.0文档 利用worker_threads模块可以使用并行执行JavaScript的线程。要访问它:const worker =… nodejs.org

成年

Tierney的最后建议是仅处理错误并像成年人一样编写一些测试。但是谁有时间呢?

小圆圈

现在,您知道了蓝色小圆圈中的大部分内容。剩下的只是关于情绪乐队和啤酒的无用事实。

有关pm2,Node和Azure的更多信息,请查看以下资源…

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「IT平头哥联盟」,公众号后台回复「资源」 免费领取我精心整理的前端进阶资源教程

JS中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。欢迎热爱技术的你一起加入交流与学习,JS中文网的使命是帮助开发者用代码改变世界

本文著作权归作者所有,如若转载,请注明出处

转载请注明:文章转载自「 Js中文网 · 前端进阶资源教程 」https://www.javascriptc.com

标题:也许,你永远都不应该直接在生产环境中运行 Node.js

链接:https://www.javascriptc.com/2983.html

« 我在淘宝做前端的这三年 — 第一年
微前端究竟好在哪?»

相关推荐

QR code