【发布时间】:2020-12-21 16:21:43
【问题描述】:
从 npm 迁移到 yarn pnp
几个月前,我们开始在我们的 monorepo 中使用 yarn2 (pnpify),因为 node_modules 确实增长到了 200K 包。多亏了 yarn2,我们将所有包的构建和部署时间从 40 分钟缩短到了 4-5 分钟,这真的很棒。
前端包很容易被 tree-shaking 和捆绑,以便创建一个小工件并上传到存储容器。
为了在集群模式下使用 pm2 运行构建,后端包(Nestjs Rest 和 GraphQl API)有点棘手。
PM2
使用 PM2,您可以在 fork 或 cluster 模式下运行您的应用程序。
在同一个端口上运行您的应用程序时,您需要使用cluster 模式。Fork 模式在启动第一个分叉后一直说端口已在使用中(这是完全合法的)
由于我们使用的是 yarn2,因此我们只能使用 yarn 作为解释器来运行我们的应用,方法是:
yarn node ./build/main.js
为了有正确的模块解析,因为节点不理解它。
问题来了:
yarn(和 npm)在集群模式下表现不佳。
这是因为您需要将节点本身用作解释器,而不是使用 yarn(或 npm)
所以我们最终得到了以下的生态系统.config.js
{
"apps": [
{
"args": "node ./build/main.js",
"exec_mode": "cluster",
"instances": "max",
"interpreter": "bash",
"name": "api",
"script": "yarn",
"time": true
}
]
}
我们将部署交付到具有多个 CPU 内核的 VM,并使用新的生态系统重新加载 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 应用程序?
【问题讨论】:
-
修复问题:package.json 在 package.json 中添加
"pm2:start": "yarn pm2 start ecosystem.config.js"ecosystem.config.js 删除interpreter和 @987654332 @ 并且只需添加 javascipt 文件以在script中执行。所以现在你可以运行yarn:pm2start -
...
yarn pm2:start