微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 Yarn PNP 构建部署时在 PM2 集群模式下运行 NestJS 从 npm 迁移到 yarn pnpPM2

如何解决使用 Yarn PNP 构建部署时在 PM2 集群模式下运行 NestJS 从 npm 迁移到 yarn pnpPM2

从 npm 迁移到 yarn pnp

几个月前,我们开始为我们的 monorepo 使用 yarn2 (pnpify),因为 node_modules 确实增长到 200K 包。多亏了 yarn2,我们将所有包的构建和部署时间从 40 分钟减少到 4-5 分钟,这真是太棒了。

前端包很容易被摇树和捆绑,以创建一个小工件并上传到存储容器。
为了在集群模式下使用 pm2 运行构建,后端包(nestjs Rest 和 GraphQl API)有点棘手。

PM2

使用 PM2,您可以在 forkcluster 模式下运行您的应用。
在同一端口上运行您的应用时,您需要使用 cluster 模式。
Fork 模式在启动第一个 fork 后一直说端口已在使用中(这是完全合法的)

由于我们使用了yarn2,因此我们只能使用yarn作为解释器运行我们的应用程序:

yarn node ./build/main.js

为了有适当的模块分辨率,因为节点不理解它。

问题来了:
yarn(和 npm)在集群模式下表现不佳。
这是因为您需要使用 node 本身作为解释器,而不是 yarn(或 npm)
所以我们最终得到了以下生态系统.config.js

{
    "apps": [
        {
            "args": "node ./build/main.js","exec_mode": "cluster","instances": "max","interpreter": "bash","name": "api","script": "yarn","time": true
        }
    ]
}

我们将部署交付到具有 1 个以上 cpu 内核的虚拟机,并使用新生态系统重新加载了 pm2 服务。一切都是绿色的,但我们注意到只有 1 个进程实际上在侦听端口 3000,而所有其他进程确实抛出了 EADDRINUSE 错误。 yarn 发出错误,而不是抛出错误,因此 PM2 认为应用程序还活着。
或者至少,这是我们的结论...

捆绑 nestJS 是不可行的:bundled-nest

我唯一的解决方案是通过执行以下操作来对 nestjs 本身进行聚类:

import { Injectable } from '@nestjs/common';
import { fork,isMaster,on } from 'cluster';
import * as os from 'os';

const numcpus = os.cpus().length;
// const randomNumber = (min: number,max: number) =>
//   Math.floor(Math.random() * max) + min;

@Injectable()
export class ClusterService {
  // eslint-disable-next-line @typescript-eslint/ban-types
  static clusterize(callback: Function): void {
    if (isMaster) {
      // eslint-disable-next-line no-plusplus
      for (let i = 0; i < numcpus; i++) {
        fork();
      }

      on('exit',(worker,code) => {
        fork();
        // eslint-disable-next-line no-console
        console.log(
          `[Cluster] worker[${worker.process.pid}] died with status: [${code}],creating new worker`,);
      });
    } else {
      callback();
    }
  }
}

并在单个实例上运行 PM2,但这感觉有点古怪,因为 PM2 可以以更好的方式为您做到这一点。

有没有办法用yarn2“弹出”node_modules,以便我们可以将应用程序作为真正的节点进程运行?
有没有办法在使用 yarn 作为解释器的同时在同一端口以集群模式运行 PM2?
如何在yarn2 中抛出错误而不是发出错误以便PM2 创建一个新进程?

...或者是否有另一种解决方案可以在 gitlab 中仅使用 npm 而不必等待 40 分钟来构建包并使用节点解释器 n pm2 运行 nestjs 应用程序?

解决方法

yarn exec pm2 start ecosystem.config.js 并且不保存 pm2 进程。 pm2 只能在 npm 模式下复活,在 yarn 模式下不会执行你的脚本。

缺点是你不能使用 pm2 启动来从 pm2 重新启动。所以你需要自己实现一个 systemd 服务,它会在启动时执行一个 yarn pm2:start

2 种可能的功能解决方案:

  • yarn2 将能够在构建步骤后弹出 .yarn 缓存以重新创建 node_modules,以便在 npm 中启动您的应用。
  • pm2 将添加一项功能,以与集群模式结合使用纱线而不是 npm 启动您的应用
,

更新

你不需要纱线来运行具有纱线模块分辨率的应用程序。
您唯一需要做的就是在使用 node 作为解释器运行应用程序时需要 .pnp.js。 将 "interpreter_args": "--require /path/to/.pnp.js", 添加到您的 pm2 配置

ecosystem.config.js:

{
  "apps": [
    {
      "name": "my-app","script": "./main.js","interpreter_args": "--require /path/to/.pnp.js","exec_mode": "cluster"
     }
  ]
}

现在您可以执行 pm2 start ecosystem.config.js 而不会遇到任何关于未找到节点模块的错误。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。