對(duì)于后臺(tái)進(jìn)程的管理,常用的工具是crontab,可用于兩種場(chǎng)景:定時(shí)任務(wù)和常駐腳本。關(guān)于常駐腳本,今天介紹一款更好用的工具:pm2,基于nodejs開發(fā)的進(jìn)程管理器,適用于后臺(tái)常駐腳本管理,同時(shí)對(duì)node網(wǎng)絡(luò)應(yīng)用有自建負(fù)載均衡功能。官方的說法,pm2 是一個(gè)帶有負(fù)載均衡功能的Node應(yīng)用的進(jìn)程管理器,個(gè)人認(rèn)為,并不準(zhǔn)確,因?yàn)閜m2支持多種語言,只是對(duì)于除node之外的其他進(jìn)程無負(fù)載均衡的能力。
一,pm2特點(diǎn):
說一些pm2有哪些優(yōu)點(diǎn)好處呢?
- 支持進(jìn)程行為配置 ,即可以通過配置,實(shí)現(xiàn)對(duì)pm2管理應(yīng)用的一些基礎(chǔ)屬性更新修改,如應(yīng)用名稱,啟動(dòng)模式等;
- 支持集群模式,支持負(fù)載均衡,但因采用nodejs的cluster模塊實(shí)現(xiàn),僅適用于nodejs進(jìn)程;
- 支持source map,此項(xiàng)針對(duì)js, source map文件是js源文件的信息文件,里面存儲(chǔ)著源文件的位置信息;
- 支持熱重啟;
- 支持部署工作流,pm2可依據(jù)測(cè)試環(huán)境和線上環(huán)境自動(dòng)部署到不同的服務(wù)器,同時(shí)運(yùn)行在不同配置下;
- 支持監(jiān)聽重啟,在文件更新等情況下可實(shí)現(xiàn)進(jìn)程自動(dòng)重啟;
- 支持linux的startup進(jìn)程啟動(dòng),startup是指系統(tǒng)boot, 進(jìn)程自啟動(dòng),如centos的chkconfig;
- 日志管理,兩種日志,pm2系統(tǒng)日志與管理的進(jìn)程日志,默認(rèn)會(huì)把進(jìn)程的控制臺(tái)輸出記錄到日志中;
- 命令自動(dòng)補(bǔ)全功能,個(gè)人感覺這個(gè)功能意義不大,而且嘗試了一下,沒有原生的linux命令自動(dòng)補(bǔ)全反應(yīng)敏捷;
- 監(jiān)控功能,pm2 monit監(jiān)控cpu和memory使用情況,keymetrics監(jiān)控更為詳細(xì);
- 支持開發(fā)調(diào)試模式,非后臺(tái)運(yùn)行,pm2-dev start <appName>;
- 支持pm2模塊開發(fā),實(shí)現(xiàn)pm2的功能擴(kuò)展;
- keymetrics監(jiān)控,比pm2 monit監(jiān)控更為詳細(xì)友好,通過web頁面展示;
- 最大內(nèi)存重啟,設(shè)置最大內(nèi)存限制,超過限制自動(dòng)重啟;
- 編程API,提供API供開發(fā)者通過編程方式靈活管理進(jìn)程;
以上簡(jiǎn)要概述了pm2進(jìn)程管理工具的特點(diǎn)。
二,pm2常用命令
常用命令通常都是比較簡(jiǎn)單。下面列舉一些pm2常用的管理命令
- pm2 start <script_file|config_file> [options] 啟動(dòng)指定應(yīng)用,如pm2 start index.js --name httpServer;
- pm2 stop <appName> [options] 停止指定應(yīng)用,如pm2 stop httpServer;
- pm2 reload|restart <appName> [options] 重啟指定應(yīng)用,如pm2 restart httpServer;
- pm2 show <appName> [options] 顯示指定應(yīng)用詳情,如pm2 show httpServer;
- pm2 delete <appName> [options] 刪除指定應(yīng)用,如pm2 delete httpServer,如果修改應(yīng)用配置行為,最好先刪除應(yīng)用后,重新啟動(dòng)方才生效,如修改腳本入口文件;
- pm2 kill 殺掉pm2管理的所有進(jìn)程;
- pm2 logs <appName> 查看指定應(yīng)用的日志,即標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤;
- pm2 monit 監(jiān)控各個(gè)應(yīng)用進(jìn)程cpu和memory使用情況;
三,pm2常用配置
pm2 配置方式
- 命令行方式pm2 start index.js --name HttpServer --interpreter node此處通過命令的選項(xiàng)配置應(yīng)用名稱為httpServer,index.js腳本文件解釋器為node,更多選項(xiàng)可查看pm2 --help獲?。?/li>
- 配置文件方式pm2配置文件方式支持yml與json格式processes.yml文件
apps:
- script : ./api.js
name : 'api-app'
instances: 4
exec_mode: cluster
- script : ./worker.js
name : 'worker'
watch : true
env :
NODE_ENV: development
env_production:
NODE_ENV: production
processes.json
{
apps : [{
name : "worker",
script : "./worker.js",
watch : true,
env: {
"NODE_ENV": "development",
},
env_production : {
"NODE_ENV": "production"
}
},{
name : "api-app",
script : "./api.js",
instances : 4,
exec_mode : "cluster"
}]}
配置項(xiàng)
- name 應(yīng)用進(jìn)程名稱;
- script 啟動(dòng)腳本路徑;
- cwd 應(yīng)用啟動(dòng)的路徑,關(guān)于script與cwd的區(qū)別舉例說明:在/home/polo/目錄下運(yùn)行/data/release/node/index.js,此處script為/data/release/node/index.js,cwd為/home/polo/;
- args 傳遞給腳本的參數(shù);
- interpreter 指定的腳本解釋器;
- interpreter_args 傳遞給解釋器的參數(shù);
- instances 應(yīng)用啟動(dòng)實(shí)例個(gè)數(shù),僅在cluster模式有效,默認(rèn)為fork;
- exec_mode 應(yīng)用啟動(dòng)模式,支持fork和cluster模式;
- watch 監(jiān)聽重啟,啟用情況下,文件夾或子文件夾下變化應(yīng)用自動(dòng)重啟;
- ignore_watch 忽略監(jiān)聽的文件夾,支持正則表達(dá)式;
- max_memory_restart 最大內(nèi)存限制數(shù),超出自動(dòng)重啟;
- env 環(huán)境變量,object類型,如{"NODE_ENV":"production", "ID": "42"};
- log_date_format 指定日志日期格式,如YYYY-MM-DD HH:mm:ss;
- error_file 記錄標(biāo)準(zhǔn)錯(cuò)誤流,$HOME/.pm2/logs/XXXerr.log),代碼錯(cuò)誤可在此文件查找;
- out_file 記錄標(biāo)準(zhǔn)輸出流,$HOME/.pm2/logs/XXXout.log),如應(yīng)用打印大量的標(biāo)準(zhǔn)輸出,會(huì)導(dǎo)致pm2日志過大;
- min_uptime 應(yīng)用運(yùn)行少于時(shí)間被認(rèn)為是異常啟動(dòng);
- max_restarts 最大異常重啟次數(shù),即小于min_uptime運(yùn)行時(shí)間重啟次數(shù);
- autorestart 默認(rèn)為true, 發(fā)生異常的情況下自動(dòng)重啟;
- cron_restart crontab時(shí)間格式重啟應(yīng)用,目前只支持cluster模式;
- force 默認(rèn)false,如果true,可以重復(fù)啟動(dòng)一個(gè)腳本。pm2不建議這么做;
- restart_delay 異常重啟情況下,延時(shí)重啟時(shí)間;
上面內(nèi)容比較枯燥無味,下面是結(jié)合自己實(shí)踐中遇到的一些坑做的思考總結(jié)。
四,fork與cluster啟動(dòng)模式
pm2啟動(dòng)進(jìn)程的支持兩種模式:fork與cluster,對(duì)于了解node的人知道,node的多進(jìn)程編程api: child_process.fork與cluster。關(guān)于pm2的fork與cluster兩者的本質(zhì)區(qū)別,個(gè)人認(rèn)為就是node API的child_process.fork與cluster的區(qū)別,stackoverflow有關(guān)于這個(gè)問題的討論 http://stackoverflow.com/questions/346****35/cluster-and-fork-mode-difference-in-pm2。下面做個(gè)粗淺的歸納:
- cluster是fork的派生,cluster支持所有cluster擁有的特性;
- fork不支持socket地址端口復(fù)用,cluster支持地址端口復(fù)用。因?yàn)橹挥衝ode的cluster模塊支持socket選項(xiàng)SO_REUSEADDR;
- fork不可以啟動(dòng)多個(gè)實(shí)例進(jìn)程,cluster可以啟動(dòng)多個(gè)實(shí)例。但node的child_process.fork是可以實(shí)現(xiàn)啟動(dòng)多個(gè)進(jìn)程的,但是為什么沒有實(shí)現(xiàn)呢?就個(gè)人理解,node多為提供網(wǎng)絡(luò)服務(wù),啟動(dòng)多個(gè)實(shí)例需要地址端口復(fù)用,此時(shí)便可使用cluster模式實(shí)現(xiàn),但fork模式并不支持地址端口復(fù)用,多實(shí)例進(jìn)程啟動(dòng)會(huì)產(chǎn)生異常錯(cuò)誤。但對(duì)于常駐任務(wù)腳本而言,不需要提供網(wǎng)絡(luò)服務(wù),此時(shí)多進(jìn)程啟動(dòng)可以實(shí)現(xiàn),同時(shí)也提高了任務(wù)處理效率。對(duì)于上述需求,可以兩種方式實(shí)現(xiàn),一是配置app0,app1,app2方式啟動(dòng)多個(gè)進(jìn)程,二是通過應(yīng)用實(shí)例自身調(diào)用child_process.fork多進(jìn)程編程實(shí)現(xiàn);
- fork模式可以應(yīng)用于其他語言,如php,python,perl,ruby,bash,coffee, 而cluster只能應(yīng)用于node;
- fork不支持定時(shí)重啟,cluster支持定時(shí)重啟。定時(shí)重啟也就是配置中的cron_restart配置項(xiàng)。github上面有作者關(guān)于fork模式下是否需要實(shí)現(xiàn)cron-like定時(shí)的討論:https://github.com/Unitech/pm2/issues/496官網(wǎng)文檔注明說,fork模式的定時(shí)重啟這個(gè)功能不久將實(shí)現(xiàn),期待中吧... ...
五,pm2的監(jiān)控
pm2的監(jiān)控有兩種方式:
- cli方式監(jiān)控pm2 monit是專門用來監(jiān)控的命令,監(jiān)控項(xiàng)包括cpu與內(nèi)存
缺點(diǎn)monit展示內(nèi)容太過粗糙,不夠詳細(xì)
pm2 list展示當(dāng)前所有pm2的管理項(xiàng)目
可以查看出每個(gè)進(jìn)程的運(yùn)行狀態(tài)。
如果需要更詳細(xì)的監(jiān)控內(nèi)容,對(duì)于cli而言一般都是可以實(shí)現(xiàn)的。
這種監(jiān)控方式的缺點(diǎn):
a. 不夠直觀,需要自己去執(zhí)行命令并分析結(jié)果;
b. 不便于多臺(tái)服務(wù)器的應(yīng)用監(jiān)控管理;
由于這些缺點(diǎn),就需要一種更好的方式去監(jiān)控我們的應(yīng)用
keymetrics監(jiān)控
keymetrics監(jiān)控是PM2的開發(fā)者的開發(fā)和維護(hù)的一款監(jiān)控工具,可以嘗試一下,安裝配置非常容易,我也只是粗淺的嘗試了一下,可以參考
http://cnodejs.org/topic/565****00ad12df5d4e050b56
本人對(duì)監(jiān)控研究不多,這里的監(jiān)控主體是應(yīng)用進(jìn)程,非服務(wù)器,就只說說我比較喜歡的幾個(gè)功能:
a. 利于多服務(wù)器監(jiān)控管理;
b. 代碼異常,可以看出程序長(zhǎng)期運(yùn)行中的穩(wěn)定性;
c. 支持應(yīng)用基本的啟動(dòng),重啟與停止等功能;
但是,keymetrics是一款商業(yè)版的監(jiān)控軟件,免費(fèi)版功能有限,且只有兩臺(tái)服務(wù)器的免費(fèi)配額,這款軟件的服務(wù)端非自建,采用的是將應(yīng)用監(jiān)控?cái)?shù)據(jù)定時(shí)上拋第三平臺(tái),對(duì)于有著眾多服務(wù)器的公司而言費(fèi)用昂貴,而且服務(wù)器與應(yīng)用服務(wù)進(jìn)程等狀態(tài)信息是敏感性數(shù)據(jù),接入到第三方平臺(tái)中無法接受。當(dāng)然,如果是服務(wù)器數(shù)量有限,能夠支付昂貴的使用費(fèi)用,無敏感數(shù)據(jù)等場(chǎng)景的話,推薦使用Keymetrics,畢竟是PM2的開發(fā)者的開發(fā)和維護(hù),功能特性很豐富。
鑒于以上問題,國(guó)內(nèi)牛人開發(fā)了一款類似的免費(fèi)工具,本人沒有研究過,名字很有趣: pm2.5。鏈接地址
http://www.open-open.com/lib/view/open145****0105.html
關(guān)于監(jiān)控,本人經(jīng)驗(yàn)不多,就不多妄言了
六,日志問題
日志系統(tǒng)對(duì)于任意應(yīng)用而言,通常都是必不可少的一個(gè)輔助功能。pm2的相關(guān)文件默認(rèn)存放于$HOME/.pm2/目錄下,其日志主要有兩類:
a. pm2自身的日志,存放于$HOME/.pm2/pm2.log;
b. pm2所管理的應(yīng)用的日志,存放于$HOME/.pm2/logs/目錄下,標(biāo)準(zhǔn)誰出日志存放于${APP_NAME}_out.log,標(biāo)準(zhǔn)錯(cuò)誤日志存放于${APP_NAME}_error.log;
這里之所以把日志單獨(dú)說明一下是因?yàn)?,如果程序開發(fā)不嚴(yán)謹(jǐn),為了調(diào)試程序,導(dǎo)致應(yīng)用產(chǎn)生大量標(biāo)準(zhǔn)輸出,使服務(wù)器本身記錄大量的日志,導(dǎo)致服務(wù)磁盤滿載問題。一般而言,pm2管理的應(yīng)用本身都有自己日志系統(tǒng),所以對(duì)于這種不必要的輸出內(nèi)容需禁用日志,重定向到/dev/null。
與crontab比較,也有類似情況,crontab自身日志,與其管理的應(yīng)用本身的輸出。應(yīng)用腳本輸出一定需要重定向到/dev/null,因?yàn)樵撦敵鰞?nèi)容會(huì)以郵件的形式發(fā)送給用戶,內(nèi)容存儲(chǔ)在郵件文件,會(huì)產(chǎn)生意向不到的結(jié)果,或會(huì)導(dǎo)致腳本壓根不被執(zhí)行;
七,穩(wěn)定運(yùn)行建議
PM2是一款非常優(yōu)秀的Node進(jìn)程管理工具,它有著豐富的特性:能夠充分利用多核CPU且能夠負(fù)載均衡、能夠幫助應(yīng)用在崩潰后、指定時(shí)間(cluster model)和超出最大內(nèi)存限制等情況下實(shí)現(xiàn)自動(dòng)重啟。
個(gè)人幾點(diǎn)看法保證常駐應(yīng)用進(jìn)程穩(wěn)定運(yùn)行:
1. 定時(shí)重啟,應(yīng)用進(jìn)程運(yùn)行時(shí)間久了或許總會(huì)產(chǎn)生一些意料之外的問題,定時(shí)可以規(guī)避一些不可測(cè)的情況;
2. 最大內(nèi)存限制,根據(jù)觀察設(shè)定合理內(nèi)存限制,保證應(yīng)用異常運(yùn)行;
3. 合理min_uptime,min_uptime是應(yīng)用正常啟動(dòng)的最小持續(xù)運(yùn)行時(shí)長(zhǎng),超出此時(shí)間則被判定為異常啟動(dòng);
4. 設(shè)定異常重啟延時(shí)restart_delay,對(duì)于異常情況導(dǎo)致應(yīng)用停止,設(shè)定異常重啟延遲可防止應(yīng)用在不可測(cè)情況下不斷重啟的導(dǎo)致重啟次數(shù)過多等問題;
5. 設(shè)置異常重啟次數(shù),如果應(yīng)用不斷異常重啟,并超過一定的限制次數(shù),說明此時(shí)的環(huán)境長(zhǎng)時(shí)間處于不可控狀態(tài),服務(wù)器異常。此時(shí)便可停止嘗試,發(fā)出錯(cuò)誤警告通知等。