使用PM2實現(xiàn)高效的應用監(jiān)控與管理功能
1. pm2
PM2 是一個流行的進程管理器,用于 Node.js 應用程序。它支持應用程序的負載均衡、自動重啟、日志管理、監(jiān)控以及多環(huán)境管理等功能。PM2讓開發(fā)者能夠以守護進程的方式運行和管理 Node.js 應用,即使在應用崩潰或服務器重啟后也能自動重啟應用。這使得 PM2非常適合在生產(chǎn)環(huán)境中部署 Node.js 應用。除此之外,PM2還支持應用的零停機更新,以及對 Docker 容器的支持。
2. 誕生背景
PM2 的誕生背景主要是為了解決 Node.js 應用程序在生產(chǎn)環(huán)境中的運維問題。在 PM2出現(xiàn)之前,Node.js 開發(fā)者經(jīng)常面臨如何有效管理和維持應用穩(wěn)定運行的挑戰(zhàn),特別是在應對應用崩潰、服務器重啟或是負載均衡等方面。
PM2的主要目標是提供一個簡單而強大的工具,幫助開發(fā)者和系統(tǒng)管理員在生產(chǎn)環(huán)境中管理和維護 Node.js 應用。它解決的關(guān)鍵問題包括:
- 自動重啟: 如果 Node.js 應用崩潰或由于某種原因停止,PM2可以自動重啟應用,確保服務的持續(xù)可用性。
- 負載均衡: PM2支持集群模式,能夠啟動多個應用實例,并在它們之間自動分配負載,提高應用的可伸縮性和可用性。
- 無停機更新: PM2允許開發(fā)者在不停止當前服務的情況下,更新 Node.js 應用到新的版本,這對于需要24/7運行的服務來說非常重要。
- 日志管理: PM2提供了日志管理的功能,使得跟蹤和調(diào)試生產(chǎn)環(huán)境中的應用更為便捷。
- 監(jiān)控: PM2包含了一個監(jiān)控系統(tǒng),可以實時查看應用的 CPU 和內(nèi)存使用情況,幫助開發(fā)者優(yōu)化應用性能。
3. 安裝
執(zhí)行以下命令來全局安裝 PM2。全局安裝意味著你可以在任何地方運行 PM2命令。
npm install pm2 -g
這條命令會將 PM2安裝到你的系統(tǒng)上,-g 參數(shù)表示全局安裝,這樣你就可以在任何目錄下使用 PM2命令。
安裝完成后,你可以運行以下命令來檢查 PM2是否正確安裝:
pm2 --version
4. 常用命令
| 命令 | 描述 | 使用示例及參數(shù) |
|---|---|---|
start | 啟動應用 | pm2 start app.jspm2 start app.js -i 4 --name myApppm2 start app.js --watch |
stop | 停止應用 | pm2 stop app.jspm2 stop 0pm2 stop all |
restart | 重啟應用 | pm2 restart app.jspm2 restart all |
delete | 刪除應用 | pm2 delete app.jspm2 delete 0pm2 delete all |
list | 列出所有應用 | pm2 list |
monit | 監(jiān)控應用 | pm2 monit |
logs | 查看應用日志 | pm2 logspm2 logs app.jspm2 logs --lines 100 |
save | 保存當前應用列表 | pm2 save |
reload | 重載應用 | pm2 reload app.jspm2 reload all |
scale | 調(diào)整集群模式下的實例數(shù)量 | pm2 scale app +1pm2 scale app 4 |
describe | 查看應用詳細信息 | pm2 describe 0 |
update | 更新 PM2守護進程 | pm2 update |
status | 查看應用狀態(tài) | pm2 status |
flush | 清空所有日志文件 | pm2 flush |
startup | 創(chuàng)建開機自啟動腳本 | pm2 startup |
unstartup | 刪除開機自啟動腳本 | pm2 unstartup |
5. 配置文件
PM2的配置文件通常被稱為ecosystem.config.js,這是一個 JavaScript 文件,允許你配置和管理應用程序的多個方面。通過使用配置文件,你可以輕松地指定環(huán)境變量、日志文件路徑、實例數(shù)量等,并且可以一次性啟動多個應用。下面詳細介紹如何使用 PM2配置文件。
基本結(jié)構(gòu)
PM2的ecosystem.config.js文件基本結(jié)構(gòu)如下:
module.exports = {
apps: [
{
name: "app1", // 應用程序名稱
script: "./app.js", // 主腳本路徑
args: "arg1 arg2", // 傳遞給腳本的參數(shù)
instances: 4, // 應用實例數(shù)
autorestart: true, // 自動重啟
watch: false, // 監(jiān)控文件變動
max_memory_restart: "1G", // 內(nèi)存超過1G 重啟
env: {
// 環(huán)境變量
NODE_ENV: "development",
},
env_production: {
// 生產(chǎn)環(huán)境變量
NODE_ENV: "production",
},
},
{
name: "app2",
script: "./app2.js",
// 其他配置...
},
],
};
主要字段解釋
- apps: 一個數(shù)組,包含了你要運行的應用的配置對象。
- name: 應用程序的名稱。
- script: 應用程序的啟動腳本或文件。
- args: 傳遞給腳本的參數(shù)。
- instances: 啟動應用實例的數(shù)量。對于無狀態(tài)的應用,可以設(shè)置為
max以根據(jù) CPU 核心數(shù)量來啟動最大實例數(shù)。 - autorestart: 如果應用崩潰或者停止,是否自動重啟。
- watch: 是否啟用文件監(jiān)控和自動重啟。
- max_memory_restart: 當應用超過指定內(nèi)存量時自動重啟。
- env: 在這個對象中,你可以指定傳遞給應用的環(huán)境變量。這些環(huán)境變量在所有環(huán)境下都會加載。
- env_production, env_development: 你可以為不同的環(huán)境指定不同的環(huán)境變量。
使用配置文件
- 啟動應用: 使用配置文件啟動應用時,運行如下命令:
pm2 start ecosystem.config.js
- 指定環(huán)境: 如果你有為不同環(huán)境定義的變量,可以在啟動時指定:
pm2 start ecosystem.config.js --env production
配置文件為應用部署提供了強大而靈活的管理方式,特別是當你需要部署多個應用或需要為應用指定特定的環(huán)境變量和配置時。通過精心設(shè)計的配置文件,你可以確保應用的部署更加一致和可預測。
6. CLI 實現(xiàn)配置文件效果
如果你不使用配置文件,而是選擇直接使用 PM2的 CLI 命令來實現(xiàn)上面提到的功能,可以通過在命令行中添加特定的選項和參數(shù)來完成。下面是如何通過 CLI 命令實現(xiàn)配置文件中提到的一些主要功能:
啟動應用并傳遞參數(shù):
pm2 start app.js --name "app1" -- arg1=value1 arg2=value2
這里
--name "app1"設(shè)定了應用的名稱,-- arg1 arg2向應用傳遞了參數(shù)。指定實例數(shù)量:
pm2 start app.js -i 4
該命令啟動了4個應用實例。如果你想要根據(jù) CPU 核心數(shù)量來啟動最大實例數(shù),可以使用
-i max。啟用自動重啟: 自動重啟是 PM2的默認行為,無需特別指定。
啟用文件監(jiān)控:
pm2 start app.js --watch
這會監(jiān)控應用目錄中文件的變動,并在變動時自動重啟應用。
限制內(nèi)存重啟:
pm2 start app.js --max-memory-restart 1G
當應用消耗的內(nèi)存超過1GB 時,PM2將自動重啟應用。
設(shè)置環(huán)境變量: 你可以在啟動命令中直接設(shè)置環(huán)境變量:
NODE_ENV=development pm2 start app.js
或者,為了同時設(shè)置多個環(huán)境變量,可以使用:
pm2 start app.js --env NODE_ENV=development,env1=13,env2=32
使用 CLI 命令直接設(shè)置這些選項的好處是快速簡便,特別是對于一次性或臨時的任務。但對于更復雜的部署,或者當你需要在多個環(huán)境中維護一致的配置時,使用配置文件將更為有效和易于管理。
7. 監(jiān)控
PM2提供了一個內(nèi)置的監(jiān)控工具,允許你實時查看運行在 PM2下的應用的性能指標,如 CPU 和內(nèi)存使用情況。這個監(jiān)控工具可以幫助你了解應用的運行狀況,及時發(fā)現(xiàn)潛在的問題。
使用 PM2監(jiān)控命令行工具

- 啟動監(jiān)控控制臺: 要查看實時的監(jiān)控數(shù)據(jù),可以在命令行中使用以下命令:
pm2 monit
- 這會打開一個交互式的監(jiān)控控制臺,其中展示了所有由 PM2管理的進程的 CPU 和內(nèi)存使用情況。
使用 PM2 Web 界面

PM2還提供了一個 Web 界面,稱為 PM2 Plus,用于更高級的監(jiān)控和管理功能,包括遠程監(jiān)控和日志管理。不過,這需要在 PM2 Plus 網(wǎng)站上注冊并設(shè)置 keymetrics 代理。
- PM2 Plus:
- 你可以訪問PM2 Plus來獲取更多關(guān)于這個服務的信息。
- 它允許你監(jiān)控關(guān)鍵指標,設(shè)置告警,查看日志,和進行實時的問題排查。
自定義指標
PM2還允許你定義自己的指標來監(jiān)控。你可以在你的應用中集成 PM2的 API 來發(fā)送自定義指標,這樣就可以在 PM2的監(jiān)控工具中查看這些指標了。
8. 其它
8.1 負載均衡下的會話管理
在使用 PM2的集群模式運行多個實例的場景下,確保會話(session)一致性是一個重要的考慮點。由于每個實例都是獨立運行的,直接在內(nèi)存中存儲會話信息可能會導致會話不一致的問題,因為用戶的后續(xù)請求可能被路由到不同的實例上,而不同的實例之間無法共享內(nèi)存中的會話信息。
為了解決這個問題,通常的做法是使用一個中央存儲來存儲會話信息,這樣不同的實例可以共享這些信息。以下是一些常見的解決方案:
使用 Redis 存儲會話: Redis 是一種常用的解決方案,它提供了快速的數(shù)據(jù)讀寫并支持數(shù)據(jù)持久化。使用 Redis 作為會話存儲,可以確保不同的實例能夠訪問和更新同一份會話數(shù)據(jù)。
使用數(shù)據(jù)庫存儲會話: 另一種常見的方法是將會話存儲在數(shù)據(jù)庫中,如 MongoDB 或 MySQL 等。這樣可以確保會話信息的一致性,但可能比使用內(nèi)存存儲或 Redis 的性能稍低。
使用其他共享存儲方案: 根據(jù)應用的具體需求,還可以考慮使用其他類型的共享存儲方案,如 Memcached、Etcd 等。
對于 Node.js 應用,如果你使用 Express 框架,可以利用express-session配合 Redis 等存儲的中間件來實現(xiàn)會話的共享。例如,使用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,
})
);
使用這種方式,無論用戶的請求被路由到哪個實例,應用都能訪問到同一份會話信息,從而避免了會話不一致的問題。確保你的會話存儲方案是可伸縮的,并且可以處理你的應用負載。
8.2 異常重啟處理
當 PM2重啟應用時,確保應用的當前狀態(tài)完成后再繼續(xù),以及在異常重啟下恢復重啟前的狀態(tài),需要在應用層面做一些策略設(shè)計。這通常涉及到優(yōu)雅的關(guān)閉處理和持久化狀態(tài)管理。
優(yōu)雅的關(guān)閉處理
捕獲關(guān)閉信號:在 Node.js 應用中,你可以監(jiān)聽如
SIGINT和SIGTERM這樣的信號,這樣當 PM2嘗試重啟應用時,你的代碼可以捕獲這些信號并執(zhí)行清理邏輯。
process.on("SIGINT", function () {
console.log("Received SIGINT. Performing graceful shutdown.");
gracefulShutdown();
});
function gracefulShutdown() {
// 在這里執(zhí)行清理操作,如關(guān)閉數(shù)據(jù)庫連接、完成正在處理的請求等
}
完成正在處理的請求:在收到關(guān)閉信號后,應用應該停止接受新的請求,但同時確保當前正在處理的請求完成。這可能涉及到跟蹤所有活躍的請求并等待它們結(jié)束。
恢復狀態(tài)
狀態(tài)持久化:為了在重啟后恢復狀態(tài),應用的關(guān)鍵狀態(tài)需要持久化,例如存儲在數(shù)據(jù)庫或文件系統(tǒng)中。這樣,在應用重啟后,可以從這些持久化的存儲中恢復狀態(tài)。
啟動時的狀態(tài)恢復邏輯:應用啟動時應該包含邏輯來檢查并恢復之前的狀態(tài)。這可能包括讀取數(shù)據(jù)庫中的數(shù)據(jù),或從文件系統(tǒng)中恢復信息等。
PM2特定策略
進程守護:PM2會守護你的應用進程,如果應用崩潰或非正常退出,它會自動重啟應用。這是通過配置 PM2的
restart策略實現(xiàn)的。零停機重啟:使用 PM2的
reload或gracefulReload命令可以實現(xiàn)零停機重啟,這對于不間斷服務的應用特別有用。這些命令會等待新的實例啟動并接收連接后,再停止舊的實例。
8.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); // 假設(shè)請求處理需要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信號后,進程確實有機會執(zhí)行清理邏輯,但這并不意味著 PM2無法再去主動 kill 進程。當你的應用捕獲SIGINT信號并進入清理階段時,PM2會等待一段時間(默認是1600毫秒),這個時間是可配置的。如果應用在這段時間內(nèi)沒有退出,PM2會發(fā)送SIGKILL信號來強制終止進程。
這意味著你的清理邏輯需要在 PM2的超時時間內(nèi)完成,以確保它能夠正常執(zhí)行并讓進程優(yōu)雅地退出。如果清理邏輯需要的時間超過了 PM2的超時閾值,你可以調(diào)整 PM2的配置來增加這個超時時間。
例如,你可以在啟動應用時通過--kill-timeout參數(shù)來設(shè)置這個超時時間:
pm2 start app.js --kill-timeout 3000
這里,--kill-timeout 3000表示 PM2將等待3000毫秒(3秒)給應用足夠的時間來處理清理邏輯。如果應用在3秒內(nèi)沒有退出,PM2將使用SIGKILL來強制終止應用。
這個機制確保了你的應用有機會在 PM2重啟或停止它之前完成必要的清理工作,同時也保留了 PM2在應用無法正確響應終止信號時強制關(guān)閉它的能力。
以上就是使用PM2實現(xiàn)高效的應用監(jiān)控與管理功能的詳細內(nèi)容,更多關(guān)于PM2應用監(jiān)控與管理的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Nodejs中session的簡單使用及通過session實現(xiàn)身份驗證的方法
session的本質(zhì)使用cookie來實現(xiàn)。本文給大家介紹Nodejs中session的簡單使用及通過session實現(xiàn)身份驗證的方法,對node.js session相關(guān)知識感興趣的朋友一起學習吧2016-02-02
nodejs爬蟲抓取數(shù)據(jù)亂碼問題總結(jié)
這篇文章主要給大家總結(jié)了下nodejs爬蟲抓取數(shù)據(jù)亂碼問題的相關(guān)資料,需要的朋友可以參考下2015-07-07
用純Node.JS彈出Windows系統(tǒng)消息提示框?qū)嵗?MessageBox)
這篇文章主要介紹了用純Node.JS彈出Windows系統(tǒng)消息提示框?qū)嵗?MessageBox),非常具有實用價值,需要的朋友可以參考下2017-05-05
使用 Node.js 對文本內(nèi)容分詞和關(guān)鍵詞抽取
這篇文章主要介紹了使用 Node.js 對文本內(nèi)容分詞和關(guān)鍵詞抽取,需要的朋友可以參考下2017-05-05
Nodejs腳本快速導出MySQL數(shù)據(jù)庫數(shù)據(jù)
在數(shù)據(jù)庫管理和數(shù)據(jù)遷移的過程中,常常需要將數(shù)據(jù)庫中的表數(shù)據(jù)和結(jié)構(gòu)進行導出,本文將使用Node.js編寫一個腳本實現(xiàn)快速從MySQL數(shù)據(jù)庫中導出所有表的數(shù)據(jù)和結(jié)構(gòu),并保存為單獨的SQL文件,需要的可以參考下2024-10-10

