使用PM2实现高效的应用监控与管理

微信搜索“好朋友乐平”关注公众号。

在这里插入图片描述


1. pm2

PM2 是一个流行的进程管理器,用于 Node.js 应用程序。它支持应用程序的负载均衡、自动重启、日志管理、监控以及多环境管理等功能。PM2让开发者能够以守护进程的方式运行和管理 Node.js 应用,即使在应用崩溃或服务器重启后也能自动重启应用。这使得 PM2非常适合在生产环境中部署 Node.js 应用。除此之外,PM2还支持应用的零停机更新,以及对 Docker 容器的支持。

2. 诞生背景

PM2 的诞生背景主要是为了解决 Node.js 应用程序在生产环境中的运维问题。在 PM2出现之前,Node.js 开发者经常面临如何有效管理和维持应用稳定运行的挑战,特别是在应对应用崩溃、服务器重启或是负载均衡等方面。

PM2的主要目标是提供一个简单而强大的工具,帮助开发者和系统管理员在生产环境中管理和维护 Node.js 应用。它解决的关键问题包括:

  1. 自动重启: 如果 Node.js 应用崩溃或由于某种原因停止,PM2可以自动重启应用,确保服务的持续可用性。
  2. 负载均衡: PM2支持集群模式,能够启动多个应用实例,并在它们之间自动分配负载,提高应用的可伸缩性和可用性。
  3. 无停机更新: PM2允许开发者在不停止当前服务的情况下,更新 Node.js 应用到新的版本,这对于需要24/7运行的服务来说非常重要。
  4. 日志管理: PM2提供了日志管理的功能,使得跟踪和调试生产环境中的应用更为便捷。
  5. 监控: PM2包含了一个监控系统,可以实时查看应用的 CPU 和内存使用情况,帮助开发者优化应用性能。

2. 安装

执行以下命令来全局安装 PM2。全局安装意味着你可以在任何地方运行 PM2命令。

npm install pm2 -g

这条命令会将 PM2安装到你的系统上,-g 参数表示全局安装,这样你就可以在任何目录下使用 PM2命令。

安装完成后,你可以运行以下命令来检查 PM2是否正确安装:

pm2 --version

3. 常用命令

命令描述使用示例及参数
start启动应用pm2 start app.js
pm2 start app.js -i 4 --name myApp
pm2 start app.js --watch
stop停止应用pm2 stop app.js
pm2 stop 0
pm2 stop all
restart重启应用pm2 restart app.js
pm2 restart all
delete删除应用pm2 delete app.js
pm2 delete 0
pm2 delete all
list列出所有应用pm2 list
monit监控应用pm2 monit
logs查看应用日志pm2 logs
pm2 logs app.js
pm2 logs --lines 100
save保存当前应用列表pm2 save
reload重载应用pm2 reload app.js
pm2 reload all
scale调整集群模式下的实例数量pm2 scale app +1
pm2 scale app 4
describe查看应用详细信息pm2 describe 0
update更新 PM2守护进程pm2 update
status查看应用状态pm2 status
flush清空所有日志文件pm2 flush
startup创建开机自启动脚本pm2 startup
unstartup删除开机自启动脚本pm2 unstartup

4. 配置文件

PM2的配置文件通常被称为ecosystem.config.js,这是一个 JavaScript 文件,允许你配置和管理应用程序的多个方面。通过使用配置文件,你可以轻松地指定环境变量、日志文件路径、实例数量等,并且可以一次性启动多个应用。下面详细介绍如何使用 PM2配置文件。

基本结构

PM2的ecosystem.config.js文件基本结构如下:

module.exports = {apps: [{name: "app1", // 应用程序名称script: "./app.js", // 主脚本路径args: "arg1 arg2", // 传递给脚本的参数instances: 4, // 应用实例数autorestart: true, // 自动重启watch: false, // 监控文件变动max_memory_restart: "1G", // 内存超过1G 重启env: {// 环境变量NODE_ENV: "development",},env_production: {// 生产环境变量NODE_ENV: "production",},},{name: "app2",script: "./app2.js",// 其他配置...},],
};

主要字段解释

  • apps: 一个数组,包含了你要运行的应用的配置对象。
  • name: 应用程序的名称。
  • script: 应用程序的启动脚本或文件。
  • args: 传递给脚本的参数。
  • instances: 启动应用实例的数量。对于无状态的应用,可以设置为max以根据 CPU 核心数量来启动最大实例数。
  • autorestart: 如果应用崩溃或者停止,是否自动重启。
  • watch: 是否启用文件监控和自动重启。
  • max_memory_restart: 当应用超过指定内存量时自动重启。
  • env: 在这个对象中,你可以指定传递给应用的环境变量。这些环境变量在所有环境下都会加载。
  • env_production, env_development: 你可以为不同的环境指定不同的环境变量。

使用配置文件

  1. 启动应用: 使用配置文件启动应用时,运行如下命令:

    pm2 start ecosystem.config.js
    
  2. 指定环境: 如果你有为不同环境定义的变量,可以在启动时指定:

    pm2 start ecosystem.config.js --env production
    

    这将使用env_production中定义的环境变量。

  3. 管理应用: 一旦应用启动,你可以使用 PM2的标准命令来管理它们,例如pm2 stop, pm2 restart, 和pm2 delete

配置文件为应用部署提供了强大而灵活的管理方式,特别是当你需要部署多个应用或需要为应用指定特定的环境变量和配置时。通过精心设计的配置文件,你可以确保应用的部署更加一致和可预测。

5. CLI 实现配置文件效果

如果你不使用配置文件,而是选择直接使用 PM2的 CLI 命令来实现上面提到的功能,可以通过在命令行中添加特定的选项和参数来完成。下面是如何通过 CLI 命令实现配置文件中提到的一些主要功能:

  1. 启动应用并传递参数:

    pm2 start app.js --name "app1" -- arg1=value1 arg2=value2
    

    这里--name "app1"设定了应用的名称,-- arg1 arg2向应用传递了参数。

  2. 指定实例数量:

    pm2 start app.js -i 4
    

    该命令启动了4个应用实例。如果你想要根据 CPU 核心数量来启动最大实例数,可以使用-i max

  3. 启用自动重启:
    自动重启是 PM2的默认行为,无需特别指定。

  4. 启用文件监控:

    pm2 start app.js --watch
    

    这会监控应用目录中文件的变动,并在变动时自动重启应用。

  5. 限制内存重启:

    pm2 start app.js --max-memory-restart 1G
    

    当应用消耗的内存超过1GB 时,PM2将自动重启应用。

  6. 设置环境变量:
    你可以在启动命令中直接设置环境变量:

    NODE_ENV=development pm2 start app.js
    

    或者,为了同时设置多个环境变量,可以使用:

    pm2 start app.js --env NODE_ENV=development,env1=13,env2=32
    
  7. 为生产环境设置环境变量:
    对于生产环境,你可以这样设置:

    NODE_ENV=production pm2 start app.js
    

使用 CLI 命令直接设置这些选项的好处是快速简便,特别是对于一次性或临时的任务。但对于更复杂的部署,或者当你需要在多个环境中维护一致的配置时,使用配置文件将更为有效和易于管理。

6. 监控

PM2提供了一个内置的监控工具,允许你实时查看运行在 PM2下的应用的性能指标,如 CPU 和内存使用情况。这个监控工具可以帮助你了解应用的运行状况,及时发现潜在的问题。

使用 PM2监控命令行工具

  1. 启动监控控制台:
    要查看实时的监控数据,可以在命令行中使用以下命令:
    pm2 monit
    
    这会打开一个交互式的监控控制台,其中展示了所有由 PM2管理的进程的 CPU 和内存使用情况。

使用 PM2 Web 界面

PM2还提供了一个 Web 界面,称为 PM2 Plus,用于更高级的监控和管理功能,包括远程监控和日志管理。不过,这需要在 PM2 Plus 网站上注册并设置 keymetrics 代理。

  1. PM2 Plus:
    • 你可以访问PM2 Plus来获取更多关于这个服务的信息。
    • 它允许你监控关键指标,设置告警,查看日志,和进行实时的问题排查。

自定义指标

PM2还允许你定义自己的指标来监控。你可以在你的应用中集成 PM2的 API 来发送自定义指标,这样就可以在 PM2的监控工具中查看这些指标了。

7. 其它

7.1 负载均衡下的会话管理

在使用 PM2的集群模式运行多个实例的场景下,确保会话(session)一致性是一个重要的考虑点。由于每个实例都是独立运行的,直接在内存中存储会话信息可能会导致会话不一致的问题,因为用户的后续请求可能被路由到不同的实例上,而不同的实例之间无法共享内存中的会话信息。

为了解决这个问题,通常的做法是使用一个中央存储来存储会话信息,这样不同的实例可以共享这些信息。以下是一些常见的解决方案:

  1. 使用 Redis 存储会话: Redis 是一种常用的解决方案,它提供了快速的数据读写并支持数据持久化。使用 Redis 作为会话存储,可以确保不同的实例能够访问和更新同一份会话数据。

  2. 使用数据库存储会话: 另一种常见的方法是将会话存储在数据库中,如 MongoDB 或 MySQL 等。这样可以确保会话信息的一致性,但可能比使用内存存储或 Redis 的性能稍低。

  3. 使用其他共享存储方案: 根据应用的具体需求,还可以考虑使用其他类型的共享存储方案,如 Memcached、Etcd 等。

对于 Node.js 应用,如果你使用 Express 框架,可以利用express-session配合 Redis 等存储的中间件来实现会话的共享。例如,使用connect-redis中间件将会话存储在 Redis 中:

const session = require("express-session");
const RedisStore = require("connect-redis")(session);app.use(session({store: new RedisStore({// Redis 服务器配置host: "localhost",port: 6379,}),secret: "your_secret",resave: false,saveUninitialized: false,})
);

使用这种方式,无论用户的请求被路由到哪个实例,应用都能访问到同一份会话信息,从而避免了会话不一致的问题。确保你的会话存储方案是可伸缩的,并且可以处理你的应用负载。

7.2 异常重启处理

当 PM2重启应用时,确保应用的当前状态完成后再继续,以及在异常重启下恢复重启前的状态,需要在应用层面做一些策略设计。这通常涉及到优雅的关闭处理和持久化状态管理。

优雅的关闭处理
  1. 捕获关闭信号:在 Node.js 应用中,你可以监听如SIGINTSIGTERM这样的信号,这样当 PM2尝试重启应用时,你的代码可以捕获这些信号并执行清理逻辑。

    process.on("SIGINT", function () {console.log("Received SIGINT. Performing graceful shutdown.");gracefulShutdown();
    });function gracefulShutdown() {// 在这里执行清理操作,如关闭数据库连接、完成正在处理的请求等
    }
    
  2. 完成正在处理的请求:在收到关闭信号后,应用应该停止接受新的请求,但同时确保当前正在处理的请求完成。这可能涉及到跟踪所有活跃的请求并等待它们结束。

恢复状态
  1. 状态持久化:为了在重启后恢复状态,应用的关键状态需要持久化,例如存储在数据库或文件系统中。这样,在应用重启后,可以从这些持久化的存储中恢复状态。

  2. 启动时的状态恢复逻辑:应用启动时应该包含逻辑来检查并恢复之前的状态。这可能包括读取数据库中的数据,或从文件系统中恢复信息等。

PM2特定策略
  • 进程守护:PM2会守护你的应用进程,如果应用崩溃或非正常退出,它会自动重启应用。这是通过配置 PM2的restart策略实现的。

  • 零停机重启:使用 PM2的reloadgracefulReload命令可以实现零停机重启,这对于不间断服务的应用特别有用。这些命令会等待新的实例启动并接收连接后,再停止旧的实例。

7.3 SIGINT 信号超时处理

const express = require("express");
const app = express();
const server = app.listen(3000, () =>console.log("Server started on port 3000")
);let activeConnections = new Set();app.get("/", (req, res) => {// 模拟长时间运行的请求const requestId = Date.now();activeConnections.add(requestId);console.log(`Request ${requestId} started`);setTimeout(() => {res.send("Hello World");activeConnections.delete(requestId);console.log(`Request ${requestId} finished`);}, 10000); // 假设请求处理需要10秒
});process.on("SIGINT", () => {console.log("Received SIGINT. Graceful shutdown start.");// 停止服务器接受新的连接server.close(() => {console.log("Server closed. No new connections are accepted.");});// 等待所有活动请求完成const checkActiveConnections = () => {if (activeConnections.size > 0) {console.log(`Waiting for ${activeConnections.size} active connections to finish.`);setTimeout(checkActiveConnections, 1000);} else {console.log("All connections finished. Exiting now.");process.exit(0);}};checkActiveConnections();
});

捕获SIGINT信号后,进程确实有机会执行清理逻辑,但这并不意味着 PM2无法再去主动 kill 进程。当你的应用捕获SIGINT信号并进入清理阶段时,PM2会等待一段时间(默认是1600毫秒),这个时间是可配置的。如果应用在这段时间内没有退出,PM2会发送SIGKILL信号来强制终止进程。

这意味着你的清理逻辑需要在 PM2的超时时间内完成,以确保它能够正常执行并让进程优雅地退出。如果清理逻辑需要的时间超过了 PM2的超时阈值,你可以调整 PM2的配置来增加这个超时时间。

例如,你可以在启动应用时通过--kill-timeout参数来设置这个超时时间:

pm2 start app.js --kill-timeout 3000

这里,--kill-timeout 3000表示 PM2将等待3000毫秒(3秒)给应用足够的时间来处理清理逻辑。如果应用在3秒内没有退出,PM2将使用SIGKILL来强制终止应用。

这个机制确保了你的应用有机会在 PM2重启或停止它之前完成必要的清理工作,同时也保留了 PM2在应用无法正确响应终止信号时强制关闭它的能力。


微信搜索“好朋友乐平”关注公众号。

github原文地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2807192.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

什么是负载均衡集群?

目录 1、集群是什么? 2、负载均衡集群技术 3、负载均衡集群技术的实现 4、实现效果如图 5、负载均衡分类 6、四层负载均衡(基于IP端口的负载均衡) 7、七层的负载均衡(基于虚拟的URL或主机IP的负载均衡) 8、四层负载与七层…

消息中间件篇之RabbitMQ-消息重复消费

一、导致重复消费的情况 1. 网络抖动。 2. 消费者挂了。 消费者消费消息后,当确认消息还没有发送到MQ时,就发生网络抖动或者消费者宕机。那当消费者恢复后,由于MQ没有收到消息,而且消费者有重试机制,消费者就会再一次消…

【Java程序设计】【C00282】基于Springboot的校园台球厅人员与设备管理系统(有论文)

基于Springboot的校园台球厅人员与设备管理系统(有论文) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的校园台球厅人员与设备管理系统 本系统分为系统功能模块、管理员功能模块以及用户功能模块。 系统功能模块&#xf…

政安晨:【机器学习基础】(一)—— 泛化:机器学习的目标

政安晨的个人主页:政安晨 欢迎 👍点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正! 简述 泛化是机器学习中的基本概念之一。它指的是通过学习…

代码随想录刷题第41天

首先是01背包的基础理论,背包问题,即如何在有限数量的货物中选取使具有一定容量的背包中所装货物价值最大。使用动规五步曲进行分析,使用二维数组do[i][j]表示下标从0到i货物装在容量为j背包中的最大价值,dp[i][j]可由不放物品i&a…

Linux---进程间通信(下)

1、System V 共享内存 原理如下图 系统调用接口介绍 int shmget(key_t key, size_t size, int shmflg) 功能:用来创建共享内存 参数 key:这个共享内存段名字,内核用key来标识共享内存size:共享内存大小shmflg:由九个权…

Vue局部注册组件实现组件化登录注册

Vue局部注册组件实现组件化登录注册 一、效果二、代码1、index.js2、App.vue3、首页4、登录(注册同理) 一、效果 注意我这里使用了element组件 二、代码 1、index.js import Vue from vue import VueRouter from vue-router import Login from ../vie…

独立版表情包小程序完整版源码前后端源码,附带系统搭建教程

搭建要求: 1.系统要求Nginx 1.18.0PHP-7.2mysql5.6,开启 ssl,php需要安装 sg11 扩展 2.设置伪静态 location / { index index.php index.html index.htm; if (!-e $request_filename) { rewrite ^/(.*)$ /index.php?s$1; } } location /a…

运维的利器–监控–zabbix–第二步:建设–部署zabbix agent--windows server系统

文章目录 在windows server 2016安装zabbix agent第一步:下载windows安装agent软件第二步:解压到指定目录第三步:配置zabbix-agent.win.conf第四步:zabbix-agent安装第五步:启动zabbix-agent客户端第六步:确…

冯诺依曼体系结构 计算机组成的金字塔

01 冯诺依曼体系结构:计算机组成的金字塔 学习计算机组成原理,到底是在学些什么呢?这个事儿,一两句话还真说不清楚。不过没关系,我们先从“装电脑”这个看起来没有什么技术含量的事情说起,来弄清楚计算机到…

旋转齿轮加载

效果演示 实现了一个旋转齿轮的动画效果。具体来说,页面背景为深灰色,中间有一个齿轮装置,包括四个齿轮。每个齿轮都有内部的齿轮条,整体呈现出旋转的效果。其中,齿轮2是顺时针旋转的,齿轮1、3、4是逆时针旋…

freemarker模板引擎结合node puppeteer库实现html生成图片

效果图: 先看效果图,以下是基于freemarker模板渲染数据,puppeteer加载html中的js及最后图片生成: 背景: 目前为止,后台java根据html模板或者一个网页路径生成图片,都不支持flex布局及最新的c…

《The Art of InnoDB》第一部分|第2章:基础原理-整体架构

第2章:整体架构 目录 第2章:整体架构 2.1 单机架构 2.1.1 Mysql架构分层 2.1.2 InnoDB架构分层 2.1.3 小结 2.2 集群架构 2.2.1 主从模式 2.2.2 Cluster模式 2.2.3 主从模式和Cluste的区别 2.2.4 小结 2.3 总结 2.1 单机架构 2.1.1 Mysql架…

目标跟踪之KCF详解

High-Speed Tracking with Kernelized Correlation Filters 使用内核化相关滤波器进行高速跟踪 大多数现代跟踪器的核心组件是判别分类器,其任务是区分目标和周围环境。为了应对自然图像变化,此分类器通常使用平移和缩放的样本补丁进行训练。此类样本集…

Android 如何添加自定义字体

Android 如何添加自定义字体 比如我要添加 jetbrains 相关字体 在 res 文件夹中添加 font 文件夹。里面放入你的字体文件 .ttf .otf,字体文件名需要是小写,只能是字母和下划线。 在 xml 布局文件中直接通过 android:fontFamily"font/jetbrainsmo…

【JVM】StringTable 字符串常量池

参考:javaGuide 字符串常量池 是 JVM 为了提升性能和减少内存消耗针对字符串(String 类)专门开辟的一块区域,主要目的是为了避免字符串的重复创建 String的不可变性 1.通过字面量的方式(区别于new)给一个…

【回顾】蚂蚁链自研TEE技术全项通过国家金融科技认证中心认证

2022年3月,蚂蚁集团自研TEE技术(HyperEnclave)通过了北京国家金融科技认证中心认证,TEE功能(CA与TA交互、数据存储、加密解密算法等)、TEE安全(硬件安全、系统软件层安全等)47个项目…

day11-项目集成SpringSecurity-今日指数

项目集成SpringSecurity 学习目标 理解自定义认证和授权过滤器流程;理解项目集成SprignSecurity流程; 第一章 自定义认证授权过滤器 1、SpringSecurity内置认证流程 通过研究SpringSecurity内置基于form表单认证的UsernamePasswordAuthenticationFi…

消息中间件篇之RabbitMQ-高可用机制

一、怎么保证高可用性 在生产环境下,使用集群来保证高可用性,一般我们采用普通集群、镜像集群、仲裁队列。 二、普通集群 普通集群,或者叫标准集群(classic cluster),具备下列特征: 1. 会在集…

第2.5章 StarRocks表设计——行列混存表

注:本篇文章阐述的是StarRocks- 3.2.3版本的行列混存表 一、概述 1.1 背景 StarRocks 基于列存格式引擎构建,在高并发场景,用户希望从系统中获取整行数据。当表宽时,列存格式将放大随机IO和读写。自3.2.3开始,StarRo…