node.js PM2部署项目_node 安装pm2-程序员宅基地

技术标签: node.js  PM2  log  前端  javascript  

文章更新
2023-05-21 更新NSSM安装服务的方式

pm2 是什么

pm2 是一个守护进程管理工具,它能帮你守护和管理你的应用程序。通常一般会在服务上线的时候使用 pm2 进行管理。本文围绕以下重点进行讲解:安装pm2;命令行部署到PM2;PM2查看日志等命令;PM2进行负载均衡;PM2配置文件模式;日志插件pm2-logrotate;持久化PM2。
在这里插入图片描述

PM2官网 https://pm2.keymetrics.io/
PM2中文网 https://pm2.fenxianglu.cn/docs/start

安装pm2

首先我们先创建一个简单的 node 服务,新建文件夹执行npm init,然后装 pm2

npm i pm2 -g

准备测试代码

准备一个pm2目录,例如D:\workspace\nodejs\pm2
新建 index1.js 和 index2.js,写两个简单的 http 服务,然后用 pm2 进行管理
在这里插入图片描述

//index1.js
let http = require("http");
let server = http.createServer();
server.on("request", function (req, res) {
    
  console.log("------------------index1");
  res.write("hello pm2 https://zhengkai.blog.csdn.net/ ");
  res.end();
});

server.listen(3001, function () {
    
  console.log(`服务器启动成功,点击 http://localhost:3000/ 进行访问`);
});
//index2.js
let http = require("http");
let server = http.createServer();
server.on("request", function (req, res) {
    
  console.log("------------------index2");
  res.write("hello pm2 https://zhengkai.blog.csdn.net/ ");
  res.end();
});

server.listen(3002, function () {
    
  console.log(`服务器启动成功,点击 http://localhost:3001/ 进行访问`);
});

通过PM2启动node.js程序

接下来我们将使用 pm2 的start命令来分别启动这两个个程序

pm2 start index1.js
pm2 start index2.js

在这里插入图片描述
之后分别访问 http://localhost:3001/ 和访问 http://localhost:3002/ , 可以看到浏览器显示“hello pm2 https://zhengkai.blog.csdn.net/”
在这里插入图片描述

另外,如果你的代码有什么update的话,可以执行pm2 restart 0 1 (在只有少数几个应用的情况下,你可以很容易知道id)
在这里插入图片描述

查看日志,执行以下命令可以看到我们程序的日志,默认只加载最后15行

pm2 log
在这里插入图片描述

并且可以看到程序的日志被归档到C:\Users\mosho\.pm2\logs\

  • indexN-out.log
  • indexN-error.log

pm2 的命令还有很多,下面列举几个

  • 启动并查看日志 pm2 start api.js --attach
  • 启动并检测变更 pm2 start api.js --watch
  • 停止 1 个/多个/所有程序 pm2 stop id/id1 id2 id3/all
  • 杀死 1 个/多个/所有程序 pm2 delete id/id1 id2 id3/all
  • 重启 1 个/多个/所有程序 pm2 restart id/id1 id2 id3/all
  • 列出应用程序 pm2 ls
  • 查看监控面板 pm2 monit
  • 查看程序数据 pm2 show [id]

停止指定id的应用
在这里插入图片描述
删除指定应用(如果你以fork模式运行,需要进行负载均衡,则最好删除后重新start)
在这里插入图片描述

如何使用PM2进行负载均衡

NodeJS 是一个异步单线程语言,倘若不做任何多线程处理直接部署到服务器上,那么它也只能使用服务器的一个线程,这样是非常浪费服务器性能的,通常我们可以改造以下项目进行多并发的支持,然后以多线程的形式运行。

注意*:运行以下命令之前,请用pm2 ls查看并确认index1在列表中没有存在,如果存在请先删除pm2 delete 0 1

使用 pm2 只需一个命令就能让我们的程序充分利用服务器的 CPU,拿 index1.js 为例:

pm2 start index1 -i max
我的电脑是 6核 12线程,它就会开 12个线程
在这里插入图片描述

pm2 start index1 -i 2
也可以手工指定是2个线程

对于cluster模式的应用,可以使用pm2 stop {name}的方式来停止所有线程,例如pm2 stop index1
在这里插入图片描述

配置文件部署PM2

上面的例子我们都是使用命令行进行管理的,这样其实挺不方便的,好在 pm2 提供了配置文件的形式。

我们直接使用命令pm2 init simple即可生成一个简单的配置文件ecosystem.config.js,修改一下让它指向我们的两个服务

module.exports = {
    
  apps: [
    {
    
      name: "index1",
      script: "./index1.js",
    },
    {
    
      name: "index2",
      script: "./index2.js",
    },
  ],
};

我们将原先的进程都 kill 掉(可以pm2 stop all 然后pm2 delete all),然后执行pm2 start ecosystem.config.js,同样的我们的两个服务都被启动了
在这里插入图片描述

进阶配置

这里可以配置一些进阶的设置,例如注入环境变量,设置日志格式,设置定时重启,设置监听模式等等。

//https://zhengkai.blog.csdn.net/
module.exports = {
    
  apps: [
    {
    
      name: "index1", //name
      script: "./index1.js", //相对于pm2 start 的相对路径
      cwd: "", //要启动的应用程序的目录
      instances: 2, //要启动实例的数量,就是上面提到的负载
      watch: true, //是否启动监听
      env: {
     NODE_ENV: "development" }, // 将出现在您的应用程序中的 env 变量
      env_xxx: {
    
        NODE_ENV: "xxx", //使用pm2注入xxx变量进行切换
      },
      log_date_format: "YYYY-MM-DD HH:mm Z", //日志时间格式
      error_file: "./log/index-error.log", //错误文件路径
      out_file: "./log/index-out.log", //输出日志文件路径
      max_restarts: 10, //最大重启数
      restart_delay: 4000, //重启延迟时间ms
      autorestart: true, //是否自动重启
      cron_restart: "0 0 3 * * ?", //定时重启 使用cron表达式,每晚3点重启
    },
    {
    
      name: "index2",
      script: "./index2.js",
    },
  ],
};

在这里插入图片描述

日志分析与pm2-logrotate插件

作为一个应用系统,日志分析也是非常重要的。但是pm2 自带的日志功能是不支持日志分割的。随着时间的推移,日志文件会越来越大,不仅会影响性能,后期排查问题也十分麻烦。

log_date_format: "YYYY-MM-DD HH:mm Z", //日志时间格式
error_file: "./log/index-error.log", //错误文件路径
out_file: "./log/index-out.log", //输出日志文件路径

所以通常我们都需要对日志进行分割。日志分割操作很简单,只需要安装pm2-logrotate插件即可,注意这里是 pm2 install

pm2 install pm2-logrotate
在这里插入图片描述

  • Compress:是否通过 gzip 压缩日志
  • max_size:单个日志文件的大小
  • retain:保留的日志文件个数
  • dateFormat:日志文件名中的日期格式,默认是 YYYY-MM-DD_HH-mm-ss
  • rotateModule:是否把 pm2 本身的日志也进行分割,
  • workerInterval:检查文件时间间隔
  • rotateInterval:设置强制分割,默认值是 0 0 * * *,意思是每天晚上 0 点分割,这里使用的是 corn 表达式,不会的可以搜索一下

pm2-logrotate的一些命令和实践

查看默认配置
pm2 conf
在这里插入图片描述

设置日志大小为1K(线上建议10M左右的size并启用compress压缩模式)
pm2 set pm2-logrotate:max_size 1K
在这里插入图片描述

安装完插件,建议停止并删除所有服务,然后重新挂载。可以看到最后有一个Module模块并提示挂载了pm2-logrotate
pm2 stop all
pm2 delete all
pm2 start ecosystem.config.js
在这里插入图片描述
在这里插入图片描述

防止Pm2服务意外终止简易方法:Windows任务计划方式挂载PM2

1.首先先把任务保存和缓存起来。

pm2 save
在这里插入图片描述

2.然后新建一个bat文件(例如叫pm2-startup.bat),内容为恢复服务

pm2 resurrect
在这里插入图片描述
在这里插入图片描述

3.打开windows自带的任务计划管理,英文版搜索Task Scheduler
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意* : 记得这里起始于,输入一下pm2项目的路径,可以避免一些运行问题(例如路径)
在这里插入图片描述
(注意:双击进入计划任务属性,把安全选项修改为“不管用户是否登陆都运行” ,否则像server上的一些service account,是不需要登陆的,那么这个任务将不会起作用)*
在这里插入图片描述
需要输入一次密码
在这里插入图片描述

防止Pm2服务意外终止强力方法:Pm2-installer

那些什么node-windows, pm2 as windows那些都过时了,试试这个吧。
https://pm2.fenxianglu.cn/docs/general/persistent-application

https://github.com/jessety/pm2-installer

单js项目部署:NSSM安装系统服务

1.首先到NSSM官网下载NSSM 2.24
http://www.nssm.cc/download
在这里插入图片描述
2.解压NSSM,找到win64/nssm.exe
在这里插入图片描述
3.执行一下命令进行安装

nssm install pm2service
在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/moshowgame/article/details/130763991

智能推荐

JWT(Json Web Token)实现无状态登录_无状态token登录-程序员宅基地

文章浏览阅读685次。1.1.什么是有状态?有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如tomcat中的session。例如登录:用户登录后,我们把登录者的信息保存在服务端session中,并且给用户一个cookie值,记录对应的session。然后下次请求,用户携带cookie值来,我们就能识别到对应session,从而找到用户的信息。缺点是什么?服务端保存大量数据,增加服务端压力 服务端保存用户状态,无法进行水平扩展 客户端请求依赖服务.._无状态token登录

SDUT OJ逆置正整数-程序员宅基地

文章浏览阅读293次。SDUT OnlineJudge#include<iostream>using namespace std;int main(){int a,b,c,d;cin>>a;b=a%10;c=a/10%10;d=a/100%10;int key[3];key[0]=b;key[1]=c;key[2]=d;for(int i = 0;i<3;i++){ if(key[i]!=0) { cout<<key[i.

年终奖盲区_年终奖盲区表-程序员宅基地

文章浏览阅读2.2k次。年终奖采用的平均每月的收入来评定缴税级数的,速算扣除数也按照月份计算出来,但是最终减去的也是一个月的速算扣除数。为什么这么做呢,这样的收的税更多啊,年终也是一个月的收入,凭什么减去12*速算扣除数了?这个霸道(不要脸)的说法,我们只能合理避免的这些跨级的区域了,那具体是那些区域呢?可以参考下面的表格:年终奖一列标红的一对便是盲区的上下线,发放年终奖的数额一定一定要避免这个区域,不然公司多花了钱..._年终奖盲区表

matlab 提取struct结构体中某个字段所有变量的值_matlab读取struct类型数据中的值-程序员宅基地

文章浏览阅读7.5k次,点赞5次,收藏19次。matlab结构体struct字段变量值提取_matlab读取struct类型数据中的值

Android fragment的用法_android reader fragment-程序员宅基地

文章浏览阅读4.8k次。1,什么情况下使用fragment通常用来作为一个activity的用户界面的一部分例如, 一个新闻应用可以在屏幕左侧使用一个fragment来展示一个文章的列表,然后在屏幕右侧使用另一个fragment来展示一篇文章 – 2个fragment并排显示在相同的一个activity中,并且每一个fragment拥有它自己的一套生命周期回调方法,并且处理它们自己的用户输_android reader fragment

FFT of waveIn audio signals-程序员宅基地

文章浏览阅读2.8k次。FFT of waveIn audio signalsBy Aqiruse An article on using the Fast Fourier Transform on audio signals. IntroductionThe Fast Fourier Transform (FFT) allows users to view the spectrum content of _fft of wavein audio signals

随便推点

Awesome Mac:收集的非常全面好用的Mac应用程序、软件以及工具_awesomemac-程序员宅基地

文章浏览阅读5.9k次。https://jaywcjlove.github.io/awesome-mac/ 这个仓库主要是收集非常好用的Mac应用程序、软件以及工具,主要面向开发者和设计师。有这个想法是因为我最近发了一篇较为火爆的涨粉儿微信公众号文章《工具武装的前端开发工程师》,于是建了这么一个仓库,持续更新作为补充,搜集更多好用的软件工具。请Star、Pull Request或者使劲搓它 issu_awesomemac

java前端技术---jquery基础详解_简介java中jquery技术-程序员宅基地

文章浏览阅读616次。一.jquery简介 jQuery是一个快速的,简洁的javaScript库,使用户能更方便地处理HTML documents、events、实现动画效果,并且方便地为网站提供AJAX交互 jQuery 的功能概括1、html 的元素选取2、html的元素操作3、html dom遍历和修改4、js特效和动画效果5、css操作6、html事件操作7、ajax_简介java中jquery技术

Ant Design Table换滚动条的样式_ant design ::-webkit-scrollbar-corner-程序员宅基地

文章浏览阅读1.6w次,点赞5次,收藏19次。我修改的是表格的固定列滚动而产生的滚动条引用Table的组件的css文件中加入下面的样式:.ant-table-body{ &amp;amp;::-webkit-scrollbar { height: 5px; } &amp;amp;::-webkit-scrollbar-thumb { border-radius: 5px; -webkit-box..._ant design ::-webkit-scrollbar-corner

javaWeb毕设分享 健身俱乐部会员管理系统【源码+论文】-程序员宅基地

文章浏览阅读269次。基于JSP的健身俱乐部会员管理系统项目分享:见文末!

论文开题报告怎么写?_开题报告研究难点-程序员宅基地

文章浏览阅读1.8k次,点赞2次,收藏15次。同学们,是不是又到了一年一度写开题报告的时候呀?是不是还在为不知道论文的开题报告怎么写而苦恼?Take it easy!我带着倾尽我所有开题报告写作经验总结出来的最强保姆级开题报告解说来啦,一定让你脱胎换骨,顺利拿下开题报告这个高塔,你确定还不赶快点赞收藏学起来吗?_开题报告研究难点

原生JS 与 VUE获取父级、子级、兄弟节点的方法 及一些DOM对象的获取_获取子节点的路径 vue-程序员宅基地

文章浏览阅读6k次,点赞4次,收藏17次。原生先获取对象var a = document.getElementById("dom");vue先添加ref <div class="" ref="divBox">获取对象let a = this.$refs.divBox获取父、子、兄弟节点方法var b = a.childNodes; 获取a的全部子节点 var c = a.parentNode; 获取a的父节点var d = a.nextSbiling; 获取a的下一个兄弟节点 var e = a.previ_获取子节点的路径 vue