pm2命令,pm2安装教程

首页 > 经验 > 作者:YD1662024-03-27 17:23:52

前言

好不容易写了一个nodejs应用,不知道该怎么部署才好:

js复制代码

const app = express(); ... app.listen(3000, '0.0.0.0, () => { console.log("server started at 0.0.0.0:3000") });

直接一把node server.js部署之后,当服务挂了,却根本不知道原因,可能这个时候想起来是不是该给我们的应用加一个日志,是不是应该给我们展示一下node应用的状态,是不是应该做一个负载均衡等等,我们写业务都忙不过来哪里有时间去写这么多东西啊!但是不写的话如果出现各种问题那就只能歇菜了,没办法就只能加班了啊!

幸好有pm2,它是nodejs进程管理工具,目前如果说它排第二没人敢排第一;它正好帮助我们做了这些功能,我们可以早点下班了!下面我们会从这些方面来学习pm2:

pm2常用功能 实战用pm2部署next应用 pm2线上故障排查 pm2原理

pm2常用功能

首先我们新建一个service.js来练习一下pm2常用功能,server.js代码如下:

js复制代码const http = require('node:http'); // Server has a 5 seconds keep-alive timeout by default http .createServer((req, res) => { res.write('hello\n'); res.end(); }) .listen(3000); console.log("http server started at 3000......")

图1

图2

图3

实战-用pm2部署next应用

next是一个react服务端渲染框架,与vue的nuxt和angular的nest齐名,我们先初始化一个项目npx create-next-app@latest

然后运行npm run dev就可以将项目运行起来,然后我们运行npm run build,得到打包文件再运行npm run start,可以在3000端口访问到该应用,接下来我们用pm2部署该应用;由于next的部署是通过npm命令而不是一个js文件来执行的所以我们需要这样来执行pm2 start "npm run start",项目就跑起来了,如图4

pm2命令,pm2安装教程(1)

图4

但是问题并没有这么简单,我们有测试环境也有生产环境,都需要部署,这个时候我们还用原来的命令来部署,就无法区分环境了

如果测试环境和生产环境端口号不一样怎么办?

第一次启动应用使用pm2 start,第二次需要使用pm2 restart,这好像也不好办?

别急我们接着讲;如果我们需要区分环境了,那么单单使用命令已经不能够满足我们的需要了,我们可以创建一个配置文件ecosystem.config.js来配置不同的环境,它的配置如下:

pm2命令,pm2安装教程(2)

pm2命令,pm2安装教程(3)

我们先为我们的项目创建一个配置文件:

js复制代码module.exports = { apps : { name:'template', }, };

突然发现我们没有nodejs的脚本文件,我们只有一个"npm run start"命令,这时可以直接调用node-modules中的next脚本,配置如下:

js复制代码 module.exports = { apps : { name:'template', script:'./node_modules/.bin/next', args:'start' }, };

当我们的应用运行时间较长,为了防止内存泄漏,我们配置一个max_memory_restart:"1G",超过这个值之后应应用重启,这样不至于应用崩溃,接下来将自动重启设置为true:autorestart: true,我们如果说想要手动进行部署控制的话还需要把watch改为false,默认情况为true,也就是说有文件改变的时候应用会自动重启,有时候我们可能会远程传输一些文件到public文件夹但是这种情况并不需要重启应用

接下来我们解决第一个问题:有测试环境和生产环境或者还有预发环境,那么我们就在配置文件中配置一下env对象,一般需要配置端口号、环境变量、主机,默认为生产环境,其他的就用env_表示:

js复制代码 module.exports = { apps : { name:'template', script:'./node_modules/.bin/next', args:'start', max_memory_restart:'1G', autorestart: true, watch: false, env_test: { ENV: 'test', PORT: 8000, HOST: '0.0.0.0', }, env: { ENV: 'prod', PORT: 8001, HOST: '0.0.0.0', }, }, };

这样配置之后我们执行pm2 start ecosystem.config.js,默认是使用的env配置,所以我们可以在8001端口访问到node应用;如果需要部署测试环境那么需要加一个env参数:pm2 start ecosystem.config.js --env test,一顿操作之后8001无法访问了,8000可以访问了,测试环境部署成功!这样我们的pm2应用就部署成功了!部署成功之后难免有时候会出现问题,或者某些接口报错了,这个时候我们需要进行故障排查

pm2线上故障排查

可以用更加复杂的案例来进行练习,但是我们这里先使用较为简单的案例进行讲解,因为故障排查的一般步骤都是差不多的;我们先运行我们当前的应用pm2 start ecosystem.config.js --env test,可以看到运行之后状态为online,别急可以等一等再查看一下状态pm2 ls,如果这个时候还是online,那么应用启动成功了一半。为什么这么说呢?我们来看一看产生故障时的两种情况:

  1. 重启了应用发现应用跑不起来了,首先我们应该想到的就是日志:pm2 logs appName:最后发现日志很多那么直接使用less查看日志,然后command G跳转到日志最后一行往上稍微翻一翻就可以看到报错,然后修复就行了
  2. 应用启动成功了,但是页面显示502,这说明应用可能一直在重复地重启,既然应用状态是online那么就可以使用可视化页面监控当前pm2进程:pm2 monit,查看当前应用内存占用、CPU占用以及实时日志,可以定位到问题;这种方式也可以排查刚出现的线上问题;这种情况就是虚假的启动成功,需要仔细斟酌
pm2原理

要了解pm2原理首先需要了解一下nodejs的cluster模块

cluster模块

如果像我们文章开头那样直接node server.js部署nodejs应用,由于js是单线程的所以只能一个进程,只能在一个CPU中进行计算,无法应用服务器的多核CPU,所以需要通过多进程分发策略调度起所有的CPU;

nodejs的cluster模块是这样进行分发的:主进程和子进程分别监听不同端口,通过主进程将请求分发给子进程,从而实现负载均衡,那么cluster如何进行进程分发呢?让我们看看主进程是如何分发的(子进程仍然使用我们开篇写的service.js):

js复制代码const cluster = require('node:cluster') ; const { cpus } = require('node:os') ; const process = require('node:process'); const numCPUs = cpus().length; if (cluster.isPrimary) { console.log(`Primary ${process.pid} is running`); // Fork workers. for (let i = 0; i < numCPUs; i ) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`worker ${worker.process.pid} died`); }); } else { require('./service.js') console.log(`Worker ${process.pid} started`); }

可以看到判断只要是主进程那么直接调用fork,fork内部其实是启动了一个Worker继续调用当前这个js但是这个时候cluster.isPrimary为false,进入子进程判断,执行service.js,有了这个基础我们再来看pm2源码

pm2源码解析

首先我们需要寻找pm2项目的入口文件,先看一看它的package.json:

pm2命令,pm2安装教程(4)

首页 1234下一页

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.