程守護(hù):從原理到實(shí)戰(zhàn)的運(yùn)維指南)
1. 項(xiàng)目緣起為什么我們需要進(jìn)程守護(hù)在服務(wù)器運(yùn)維和后臺(tái)服務(wù)開發(fā)中我們經(jīng)常會(huì)遇到一個(gè)經(jīng)典且棘手的問題如何確保一個(gè)關(guān)鍵的服務(wù)進(jìn)程能夠7x24小時(shí)不間斷地運(yùn)行你可能會(huì)說寫個(gè)腳本用nohup 啟動(dòng)或者用systemd配置一個(gè)服務(wù)。這些方法確實(shí)可行但當(dāng)你管理的服務(wù)數(shù)量增多或者進(jìn)程行為變得復(fù)雜時(shí)它們的局限性就暴露無遺。nohup啟動(dòng)的進(jìn)程如果意外崩潰了不會(huì)自動(dòng)重啟。systemd雖然功能強(qiáng)大但它的配置相對(duì)復(fù)雜且對(duì)于需要管理大量子進(jìn)程、需要按特定順序啟動(dòng)、或者需要詳細(xì)日志切割的場(chǎng)景配置起來并不直觀。更重要的是systemd的設(shè)計(jì)初衷是管理系統(tǒng)服務(wù)對(duì)于開發(fā)者或運(yùn)維人員管理自己的應(yīng)用進(jìn)程有時(shí)顯得“殺雞用牛刀”不夠輕量和靈活。這時(shí)一個(gè)專門為“進(jìn)程守護(hù)”而生的工具就顯得尤為重要。Supervisor正是這樣一個(gè)工具。它不是一個(gè)龐大的監(jiān)控平臺(tái)而是一個(gè)專注解決單一核心問題的“瑞士軍刀”確保你的進(jìn)程像被一個(gè)盡職的管家一樣看護(hù)著一旦進(jìn)程掛掉管家會(huì)立刻察覺并嘗試重啟它。這個(gè)“管家”本身非常輕量、配置簡(jiǎn)單幾乎不消耗系統(tǒng)資源卻能極大地提升服務(wù)的可靠性。我最初接觸 Supervisor是因?yàn)橐粋€(gè)用 Python 寫的異步任務(wù)隊(duì)列服務(wù)。這個(gè)服務(wù)偶爾會(huì)因?yàn)閮?nèi)存泄漏或外部依賴異常而崩潰。在深夜收到報(bào)警短信然后手動(dòng)登錄服務(wù)器重啟服務(wù)這種經(jīng)歷實(shí)在令人疲憊。引入 Supervisor 后這類問題基本消失了。它不僅能自動(dòng)重啟崩潰的進(jìn)程還能集中管理所有守護(hù)進(jìn)程的啟動(dòng)、停止、狀態(tài)查看和日志讓運(yùn)維工作變得清晰可控。2. Supervisor 核心機(jī)制它到底是怎么“守護(hù)”的要理解 Supervisor 的價(jià)值我們需要先拆解“進(jìn)程守護(hù)”這個(gè)需求背后的幾個(gè)關(guān)鍵動(dòng)作啟動(dòng)、監(jiān)控、重啟、管理。Supervisor 正是圍繞這幾個(gè)動(dòng)作設(shè)計(jì)的。2.1 核心架構(gòu)Client-Server 模型Supervisor 采用經(jīng)典的 C/S客戶端-服務(wù)器架構(gòu)。這和我們常聽到的 Prometheus、Zabbix 這類中心化監(jiān)控系統(tǒng)有本質(zhì)區(qū)別。服務(wù)端 (supervisord)這是一個(gè)常駐后臺(tái)的守護(hù)進(jìn)程是 Supervisor 的核心大腦。它負(fù)責(zé)讀取配置文件根據(jù)配置啟動(dòng)和管理所有被托管的子進(jìn)程我們稱之為program。supervisord自身會(huì)作為一個(gè)系統(tǒng)服務(wù)通常由systemd管理啟動(dòng)確保監(jiān)控者本身是可靠的??蛻舳?(supervisorctl)這是一個(gè)命令行工具用于與supervisord服務(wù)端交互。通過它你可以執(zhí)行start、stop、restart、status等命令來管理具體的子進(jìn)程而無需直接操作進(jìn)程的 PID 或發(fā)送信號(hào)。這種分離的設(shè)計(jì)帶來了清晰的管理邊界。你通過一個(gè)統(tǒng)一的入口supervisorctl管理所有服務(wù)而底層的進(jìn)程生命周期管理則由穩(wěn)定可靠的服務(wù)端負(fù)責(zé)。2.2 監(jiān)控與重啟策略不僅僅是“崩潰了再拉起來”很多人對(duì)進(jìn)程守護(hù)的理解停留在“進(jìn)程退出碼非0就重啟”。Supervisor 的監(jiān)控策略要精細(xì)得多主要通過配置項(xiàng)來實(shí)現(xiàn)autostarttrue當(dāng)supervisord本身啟動(dòng)時(shí)是否自動(dòng)啟動(dòng)該程序。這保證了服務(wù)器重啟后你的服務(wù)也能自動(dòng)恢復(fù)。autorestart這是重啟策略的核心有三個(gè)選項(xiàng)unexpected默認(rèn)只有當(dāng)進(jìn)程的退出狀態(tài)碼不在exitcodes列表默認(rèn)是0, 2中時(shí)才自動(dòng)重啟。這意味著你可以通過讓進(jìn)程返回0或2來正常停止它而不會(huì)被誤重啟。true無論退出碼是什么都無條件重啟。false從不自動(dòng)重啟。startretries在放棄并認(rèn)為進(jìn)程進(jìn)入FATAL狀態(tài)之前嘗試重啟的最大次數(shù)。這對(duì)于處理那些啟動(dòng)時(shí)就存在致命錯(cuò)誤如配置錯(cuò)誤的進(jìn)程非常有用避免陷入無限重啟的死循環(huán)。startsecs程序啟動(dòng)后需要持續(xù)運(yùn)行多少秒才被認(rèn)為啟動(dòng)成功。如果進(jìn)程在此時(shí)長(zhǎng)內(nèi)退出則被視為啟動(dòng)失敗計(jì)入startretries。這對(duì)于需要一定初始化時(shí)間的服務(wù)如連接數(shù)據(jù)庫至關(guān)重要。一個(gè)實(shí)戰(zhàn)場(chǎng)景你有一個(gè)Web API服務(wù)它正常關(guān)閉時(shí)應(yīng)返回退出碼0。如果你配置autorestartunexpected那么當(dāng)你通過supervisorctl stop yourapp停止它時(shí)Supervisor 不會(huì)重啟它。只有當(dāng)它因?yàn)槲床东@的異常崩潰退出碼非0,2時(shí)才會(huì)觸發(fā)自動(dòng)重啟。這實(shí)現(xiàn)了對(duì)“異常退出”和“正常停止”的區(qū)分處理。2.3 日志管理問題排查的生命線Supervisor 另一個(gè)被低估的強(qiáng)大功能是統(tǒng)一的日志管理。它為標(biāo)準(zhǔn)輸出stdout和標(biāo)準(zhǔn)錯(cuò)誤stderr分別提供了重定向和輪轉(zhuǎn)rotate的能力。stdout_logfile/stderr_logfile你可以指定日志文件的路徑。Supervisor 會(huì)確保即使目錄不存在也會(huì)創(chuàng)建需有權(quán)限。stdout_logfile_maxbytes/stdout_logfile_backups這實(shí)現(xiàn)了日志輪轉(zhuǎn)。例如設(shè)置maxbytes50MB和backups10當(dāng)日志文件達(dá)到50MB時(shí)Supervisor 會(huì)自動(dòng)將其重命名為yourapp.log.1并創(chuàng)建新的yourapp.log最多保留10個(gè)歷史文件。這完美解決了日志文件無限膨脹占滿磁盤的問題無需再依賴logrotate等外部工具。stdout_logfile_N你甚至可以為同一個(gè)程序的不同日志級(jí)別配置不同的文件。踩坑經(jīng)驗(yàn)務(wù)必為stderr配置獨(dú)立的日志文件。很多運(yùn)行時(shí)錯(cuò)誤和異常堆棧信息都輸出到stderr。如果和stdout混在一起或者沒有重定向到文件默認(rèn)是AUTO這些關(guān)鍵的排錯(cuò)信息就會(huì)丟失讓你在問題發(fā)生時(shí)束手無策。3. 從零到一Supervisor 的安裝與基礎(chǔ)配置理論講完了我們動(dòng)手把它用起來。Supervisor 本身由 Python 編寫因此安裝非常方便。3.1 環(huán)境準(zhǔn)備與安裝在大多數(shù) Linux 發(fā)行版上都可以通過包管理器安裝。這里以 CentOS/RHEL 和 Ubuntu 為例。# CentOS/RHEL 7/8 sudo yum install epel-release sudo yum install supervisor # Ubuntu/Debian sudo apt-get update sudo apt-get install supervisor安裝完成后系統(tǒng)會(huì)自動(dòng)創(chuàng)建以下關(guān)鍵目錄和文件主配置文件/etc/supervisord.conf配置目錄/etc/supervisord.d/通常用于存放各個(gè)程序的獨(dú)立配置服務(wù)文件/usr/lib/systemd/system/supervisord.serviceCentOS或/etc/init.d/supervisorUbuntu但現(xiàn)代版本也多用 systemd默認(rèn)日志路徑/var/log/supervisor/安裝后Supervisor 的服務(wù)supervisord默認(rèn)不會(huì)自動(dòng)啟動(dòng)我們需要先配置它。3.2 主配置文件解析與優(yōu)化打開/etc/supervisord.conf你會(huì)發(fā)現(xiàn)它很長(zhǎng)但大部分是注釋。我們關(guān)注幾個(gè)核心部分[unix_http_server] file/var/run/supervisor.sock ; UNIX socket 文件路徑supervisorctl 通過它通信 ;chmod0700 ; socket文件的權(quán)限默認(rèn)即可 [supervisord] logfile/var/log/supervisor/supervisord.log ; 守護(hù)進(jìn)程自身的日志 logfile_maxbytes50MB ; 主日志輪轉(zhuǎn)大小 logfile_backups10 ; 主日志備份數(shù)量 loglevelinfo ; 日志級(jí)別 (debug, info, warn, error) pidfile/var/run/supervisord.pid ; pid文件路徑 nodaemonfalse ; 是否在前臺(tái)運(yùn)行false即后臺(tái)守護(hù) minfds1024 ; 最小文件描述符限制 minprocs200 ; 最小進(jìn)程數(shù)限制 [rpcinterface:supervisor] supervisor.rpcinterface_factory supervisor.rpcinterface:make_main_rpcinterface [supervisorctl] serverurlunix:///var/run/supervisor.sock ; 使用UNIX socket連接 [include] files /etc/supervisord.d/*.conf ; 包含子配置目錄關(guān)鍵配置項(xiàng)解讀與建議[include]部分這是最佳實(shí)踐的關(guān)鍵。它告訴supervisord去加載/etc/supervisord.d/目錄下所有以.conf結(jié)尾的文件。這意味著你可以為每個(gè)要守護(hù)的應(yīng)用程序創(chuàng)建一個(gè)獨(dú)立的配置文件例如my_web_api.conf、celery_worker.conf。這樣做的好處是配置清晰、易于管理增刪服務(wù)時(shí)互不影響。minfds和minprocs這兩個(gè)參數(shù)設(shè)置了supervisord進(jìn)程自身所需的資源下限。如果你的服務(wù)器上運(yùn)行著大量被守護(hù)的進(jìn)程可能需要適當(dāng)調(diào)高這些值特別是minfds文件描述符。一個(gè)簡(jiǎn)單的估算方法是每個(gè)被守護(hù)的進(jìn)程至少需要幾個(gè)文件描述符用于日志、socket等總需求應(yīng)小于minfds。日志路徑確保/var/log/supervisor目錄存在且supervisord進(jìn)程用戶通常是 root有寫入權(quán)限。3.3 編寫你的第一個(gè)進(jìn)程守護(hù)配置假設(shè)我們要守護(hù)一個(gè)簡(jiǎn)單的 Python HTTP 服務(wù)器腳本位于/opt/myapp/app.py。我們?cè)?etc/supervisord.d/下創(chuàng)建文件myapp.conf。[program:my_python_app] ; 程序唯一標(biāo)識(shí)用于 supervisorctl 操作 commandpython3 /opt/myapp/app.py ; 啟動(dòng)命令必須是前臺(tái)運(yùn)行的程序 directory/opt/myapp ; 執(zhí)行命令前先切換到此目錄 userwww-data ; 使用哪個(gè)用戶身份運(yùn)行進(jìn)程按需修改 autostarttrue ; supervisord啟動(dòng)時(shí)自動(dòng)啟動(dòng) autorestartunexpected ; 默認(rèn)策略異常退出時(shí)重啟 startretries3 ; 啟動(dòng)失敗后的重試次數(shù) startsecs5 ; 啟動(dòng)后持續(xù)5秒才算成功 stdout_logfile/var/log/supervisor/myapp_out.log ; 標(biāo)準(zhǔn)輸出日志 stdout_logfile_maxbytes50MB ; 輸出日志輪轉(zhuǎn)大小 stdout_logfile_backups10 ; 輸出日志備份數(shù)量 stderr_logfile/var/log/supervisor/myapp_err.log ; 錯(cuò)誤日志獨(dú)立存放 stderr_logfile_maxbytes50MB stderr_logfile_backups10 environmentPYTHONPATH/opt/myapp,PORT8080 ; 設(shè)置環(huán)境變量配置要點(diǎn)解析command這是最重要的指令。必須確保你啟動(dòng)的程序是“前臺(tái)進(jìn)程”。很多程序如某些 Java 應(yīng)用、nginx默認(rèn)方式啟動(dòng)后會(huì)將自己轉(zhuǎn)為后臺(tái)守護(hù)進(jìn)程daemonize。對(duì)于 Supervisor 來說這意味著它啟動(dòng)了一個(gè)立即退出的父進(jìn)程然后父進(jìn)程 fork 出的子進(jìn)程在后臺(tái)運(yùn)行。Supervisor 會(huì)認(rèn)為父進(jìn)程已退出從而可能觸發(fā)重啟導(dǎo)致多個(gè)子進(jìn)程互相沖突。因此對(duì)于這類程序必須查找其啟動(dòng)參數(shù)關(guān)閉 daemon 模式例如nginx -g daemon off;。user以非 root 用戶運(yùn)行服務(wù)是安全最佳實(shí)踐。請(qǐng)確保該用戶對(duì)command中的可執(zhí)行文件、directory以及日志文件目錄有相應(yīng)的執(zhí)行和讀寫權(quán)限。environment可以在這里傳遞環(huán)境變量非常靈活。這對(duì)于需要不同配置如開發(fā)、測(cè)試、生產(chǎn)的應(yīng)用非常有用。3.4 啟動(dòng)與管理服務(wù)配置完成后我們需要啟動(dòng)supervisord服務(wù)并讓它管理我們的應(yīng)用。# 1. 啟動(dòng) supervisord 守護(hù)進(jìn)程以 systemd 為例 sudo systemctl start supervisord sudo systemctl enable supervisord # 設(shè)置開機(jī)自啟 # 2. 重新加載配置文件當(dāng)你在 /etc/supervisord.d/ 下新增或修改了配置后 sudo supervisorctl reread # 讀取新的配置 sudo supervisorctl update # 根據(jù)新配置更新進(jìn)程組會(huì)重啟有變動(dòng)的程序 # 3. 管理具體程序 sudo supervisorctl status my_python_app # 查看狀態(tài) sudo supervisorctl start my_python_app # 啟動(dòng) sudo supervisorctl stop my_python_app # 停止 sudo supervisorctl restart my_python_app # 重啟 sudo supervisorctl tail -f my_python_app stdout # 實(shí)時(shí)查看標(biāo)準(zhǔn)輸出日志 sudo supervisorctl tail -f my_python_app stderr # 實(shí)時(shí)查看錯(cuò)誤日志 # 4. 管理所有程序 sudo supervisorctl status all sudo supervisorctl restart all sudo supervisorctl stop all一個(gè)常見問題修改了程序的配置文件如myapp.conf后直接運(yùn)行sudo supervisorctl restart my_python_app并不會(huì)使新的環(huán)境變量或命令生效。必須先用reread和update。update命令很智能對(duì)于配置未改變的程序它不會(huì)做任何操作對(duì)于配置改變的程序它會(huì)按順序重啟如果autorestart配置允許的話。4. 進(jìn)階實(shí)戰(zhàn)復(fù)雜場(chǎng)景下的配置與排錯(cuò)掌握了基礎(chǔ)用法我們來看看 Supervisor 如何應(yīng)對(duì)更復(fù)雜的生產(chǎn)環(huán)境需求。4.1 進(jìn)程組管理一鍵操作關(guān)聯(lián)服務(wù)當(dāng)你有多個(gè)相關(guān)聯(lián)的進(jìn)程需要統(tǒng)一管理時(shí)比如一個(gè) Web 應(yīng)用及其配套的異步任務(wù)隊(duì)列 Worker可以使用[group]配置。; 假設(shè)已有 [program:web_app] 和 [program:celery_worker] 的配置 [group:my_application] programsweb_app, celery_worker ; 將兩個(gè)程序歸入一個(gè)組 priority999 ; 可選控制啟動(dòng)/停止順序現(xiàn)在你可以通過組名來批量操作sudo supervisorctl start my_application: # 啟動(dòng)組內(nèi)所有程序 sudo supervisorctl status my_application: # 查看組內(nèi)所有狀態(tài)這比單獨(dú)操作每個(gè)程序方便得多尤其在服務(wù)部署和更新時(shí)。4.2 啟動(dòng)順序與依賴關(guān)系Supervisor 本身不直接提供“A 啟動(dòng)成功后再啟動(dòng) B”的強(qiáng)依賴管理。但可以通過一些模式來模擬使用startsecs和業(yè)務(wù)層檢查對(duì)于有依賴的服務(wù)如應(yīng)用依賴數(shù)據(jù)庫將依賴服務(wù)的startsecs設(shè)置得足夠長(zhǎng)確保它在應(yīng)用啟動(dòng)時(shí)已經(jīng)就緒。同時(shí)在應(yīng)用的啟動(dòng)命令或初始化腳本中加入對(duì)依賴服務(wù)的健康檢查如循環(huán)檢測(cè)數(shù)據(jù)庫端口是否可連接檢查通過后再啟動(dòng)主邏輯。使用priority參數(shù)在[program]或[group]中設(shè)置priority值數(shù)值越小優(yōu)先級(jí)越高。當(dāng)執(zhí)行supervisorctl start all時(shí)會(huì)按優(yōu)先級(jí)從高到低啟動(dòng)stop all時(shí)則相反。這可以控制一個(gè)大致的順序但無法保證“完全就緒”。更可靠的方案對(duì)于復(fù)雜的啟動(dòng)依賴建議將協(xié)調(diào)邏輯放在外部部署腳本或配置管理工具如 Ansible中而不是完全依賴 Supervisor。4.3 深入日志與事件監(jiān)聽Supervisor 支持事件監(jiān)聽機(jī)制允許你在進(jìn)程狀態(tài)發(fā)生變化如啟動(dòng)、退出、失敗時(shí)觸發(fā)自定義腳本。這可以用來發(fā)送報(bào)警如郵件、Slack、釘釘、記錄審計(jì)日志等。配置在supervisord.conf的[eventlistener:xxx]部分原理是配置一個(gè)特殊的program它從標(biāo)準(zhǔn)輸入讀取事件通知。配置相對(duì)復(fù)雜但對(duì)于構(gòu)建自動(dòng)化運(yùn)維流水線很有價(jià)值。一個(gè)更簡(jiǎn)單的替代方案是利用獨(dú)立的日志監(jiān)控工具如logwatch、filebeat發(fā)送到 ELK來監(jiān)控 Supervisor 的日志文件supervisord.log或程序的stderr_logfile從中解析出進(jìn)程失敗事件并報(bào)警。4.4 常見問題排查指南即使配置正確在實(shí)際運(yùn)行中也可能遇到問題。以下是一些典型的排查思路問題一進(jìn)程狀態(tài)一直是 STARTING 或 BACKOFF可能原因startsecs時(shí)間設(shè)置太短程序在此時(shí)限內(nèi)未能成功啟動(dòng)例如需要連接的外部服務(wù)超時(shí)。排查使用sudo supervisorctl tail myapp stderr查看錯(cuò)誤日志通常會(huì)有啟動(dòng)失敗的堆棧信息。檢查command命令是否能在手動(dòng)執(zhí)行時(shí)在前臺(tái)正常運(yùn)行。特別注意環(huán)境變量和路徑。適當(dāng)增加startsecs的值給程序更長(zhǎng)的啟動(dòng)緩沖期。問題二進(jìn)程不斷重啟狀態(tài)在 FATAL 和 STARTING 間循環(huán)可能原因程序存在啟動(dòng)期致命錯(cuò)誤每次啟動(dòng)都立即失敗。startretries次數(shù)用盡后進(jìn)入 FATAL 狀態(tài)但由于autorestarttrue或其它配置又被嘗試重啟。排查同樣是第一時(shí)間查看stderr日志。檢查程序所需的資源端口是否被占用、配置文件是否存在且格式正確、依賴的數(shù)據(jù)庫/Redis 是否可達(dá)。臨時(shí)將autorestart改為false然后手動(dòng)start觀察立即失敗的原因。問題三通過 supervisorctl stop 無法停止進(jìn)程可能原因程序沒有正確處理SIGTERM信號(hào)Supervisor 默認(rèn)先發(fā)送SIGTERM等待stopwaitsecs秒后再發(fā)送SIGKILL。解決方案在程序配置中增加stopsignalINT或stopsignalQUIT嘗試不同的停止信號(hào)。在程序配置中增加stopasgrouptrue和killasgrouptrue。這確保 Supervisor 向整個(gè)進(jìn)程組發(fā)送停止信號(hào)對(duì)于那些自己又 fork 了子進(jìn)程的程序尤其有效。確保你的應(yīng)用程序代碼正確監(jiān)聽了終止信號(hào)并實(shí)現(xiàn)了優(yōu)雅關(guān)閉邏輯。問題四日志文件沒有生成或沒有內(nèi)容可能原因權(quán)限問題。supervisord進(jìn)程的運(yùn)行用戶默認(rèn)是 root對(duì)日志文件路徑?jīng)]有寫權(quán)限或者程序本身沒有輸出到標(biāo)準(zhǔn)輸出/錯(cuò)誤。排查檢查日志文件所在目錄的權(quán)限ls -ld /var/log/supervisor。檢查程序配置中的user確保該用戶對(duì)日志文件有寫權(quán)限。一個(gè)技巧是將日志文件放在該用戶的家目錄或/tmp下測(cè)試。在程序的command中可以嘗試重定向如commandyour_cmd /tmp/debug.log 21先確認(rèn)程序本身有輸出。5. Supervisor 在監(jiān)控體系中的定位與邊界在文章開頭提到的眾多熱詞中我們看到了 Prometheus、Zabbix、ELK 等強(qiáng)大的監(jiān)控系統(tǒng)。Supervisor 與它們的關(guān)系是什么是替代還是互補(bǔ)明確的定位Supervisor 是“進(jìn)程生命周期管理器”而非“系統(tǒng)監(jiān)控平臺(tái)”。Prometheus/Grafana擅長(zhǎng)收集和可視化指標(biāo)如 CPU 使用率、內(nèi)存消耗、請(qǐng)求 QPS、延遲等。它告訴你服務(wù)的“健康度”和“性能”。Zabbix一個(gè)功能更全面的監(jiān)控告警平臺(tái)除了指標(biāo)還能監(jiān)控網(wǎng)絡(luò)、硬件、服務(wù)存活等告警功能強(qiáng)大。ELK (Elasticsearch, Logstash, Kibana)核心是日志的集中收集、檢索與分析。Supervisor核心是確保進(jìn)程持續(xù)運(yùn)行。它不關(guān)心 CPU 是多少只關(guān)心進(jìn)程是不是在RUNNING狀態(tài)。它們?nèi)绾螀f(xié)作一個(gè)理想的監(jiān)控架構(gòu)是分層的底層守護(hù)Supervisor 負(fù)責(zé)保證進(jìn)程本身不消失。如果進(jìn)程崩潰它負(fù)責(zé)第一時(shí)間拉起來這是服務(wù)可用的最基礎(chǔ)保障。指標(biāo)監(jiān)控Prometheus 通過 Node Exporter 收集服務(wù)器指標(biāo)通過應(yīng)用自身暴露的/metrics端點(diǎn)如 Spring Boot Actuator或特定 Exporter如mysql_exporter,redis_exporter收集業(yè)務(wù)和中間件指標(biāo)。當(dāng)某個(gè)指標(biāo)異常如內(nèi)存持續(xù)增長(zhǎng)、錯(cuò)誤率飆升時(shí)通過 Alertmanager 觸發(fā)告警。此時(shí)即使進(jìn)程還在運(yùn)行Supervisor 認(rèn)為狀態(tài)是 RUNNINGPrometheus 也能發(fā)現(xiàn)其內(nèi)部已經(jīng)“不健康”了。日志聚合Filebeat 收集 Supervisor 管理的應(yīng)用日志stdout_logfile發(fā)送到 ELK 棧。當(dāng)出現(xiàn)錯(cuò)誤時(shí)可以在 Kibana 中快速搜索和定位問題根源。綜合告警Zabbix 可以作為一個(gè)綜合告警收斂中心接收來自 Prometheus、ELK通過 Webhook、甚至直接監(jiān)控 Supervisor 的 HTTP API如果開啟的告警進(jìn)行去重、分級(jí)并通知到人。具體到 Supervisor 的監(jiān)控你可以寫一個(gè)簡(jiǎn)單的腳本定期調(diào)用supervisorctl status并解析輸出如果發(fā)現(xiàn)任何進(jìn)程狀態(tài)不是RUNNING就發(fā)送告警。更高級(jí)的做法是啟用 Supervisor 的 HTTP Server在supervisord.conf中配置[inet_http_server]然后使用 Prometheus 的blackbox_exporter或自定義 Exporter 去查詢其 XML-RPC 接口將進(jìn)程狀態(tài)作為指標(biāo)暴露給 Prometheus從而實(shí)現(xiàn)統(tǒng)一的監(jiān)控面板和告警規(guī)則。所以不要試圖用 Supervisor 去做它不擅長(zhǎng)的事情。它的職責(zé)單一而明確當(dāng)好進(jìn)程的守護(hù)者。將指標(biāo)監(jiān)控、日志分析、分布式追蹤如 SkyWalking, Jaeger等任務(wù)交給更專業(yè)的工具讓 Supervisor 專注于“活著”這件事。這種職責(zé)分離的架構(gòu)才是穩(wěn)定且易于維護(hù)的。