Supervisor 管理進程服務重啓報警(Event & Listener 監控進程並報警)

一、需求:

服務、進程等都被 Supervisor 管理,想實現 被管理的程序異常退出後,或者程序嘗試重啓多次失敗後,Supervisor可以告警通知。

二、實現思路

Event 是在 Supervisor 3.0 引入的一個高級特性,如果只簡單使用 Supervisor 管理進程,則不需要了解 Event。

但如果希望監控 Supervisor 管理的進程的各種狀態(如: 啓動、退出、失敗、退出狀態碼 …)並支持告警,才需要了解Event。

利用 Supervisor 的 Event & Listener 功能進行訂閱異常退出事件,並進行報警處理。

Supervisor 官方對其 Event 機制的描述是:一個進程的監控/通知框架

該機制主要通過一個 event listener 訂閱 event 通知實現。當被 Supervisor 管理的進程有特定行爲的時候,supervisor 就會自動發出對應類型的 event。即使沒有配置 listener,這些 event 也是會發的;如果配置了 listener 並監聽該類型的 event,那麼這個 listener 就會接收到該 event。 event listener 需要自己實現,並像 program 一樣,作爲 superviosr 的子進程運行。

三、具體配置實現

1、配置事件監聽器

主管事件偵聽器是通過 配置文件中的[eventlistener:x]指定的。關於Supervisor [eventlistener:x] 在配置中允許的鍵方面,幾乎與supervisor [program:x]完全一樣,只是Supervisor不遵循事件偵聽器進程的“捕獲模式”輸出(即事件偵聽器不能是 PROCESS_COMMUNICATIONS_EVENT事件生成器)。因此,在事件``偵聽器的配置中指定stdout_capture_maxbytesstderr_capture_maxbytes是錯誤的。可以放入配置文件的事件偵聽器部分的數量沒有人爲限制。

vim /etc/supervisord.d/eventlistener.ini

[eventlistener:mylistener]
command=/opt/my_custom_listener.py  ; 自定義的監控程序
events=PROCESS_STATE_EXITED,PROCESS_STATE_FATAL,TICK_60  ; 監控事件
; 下面的配置和`[program:x]`完全一樣
autostart=true
autorestart=true
log_stdout=true
log_stderr=true
stdout_logfile=/opt/supervisor_event_exited-stdout.log
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=3
buffer_size=10
stderr_logfile=/opt/supervisor_event_exited-stderr.log
stderr_logfile_maxbytes=50MB
stderr_logfile_backups=3

2、配置監聽器腳本

vim /opt/my_custom_listener.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
from supervisor import childutils


def write_stdout(s):
    # only eventlistener protocol messages may be sent to stdout
    sys.stdout.write(s)
    sys.stdout.flush()

def write_stderr(s):
    sys.stderr.write(s)
    sys.stderr.flush()

def main():
    while 1:
        # transition from ACKNOWLEDGED to READY
        write_stdout('READY\n')

        # read header line and print it to stderr
        line = sys.stdin.readline()
        write_stderr(line)

        # read event payload and print it to stderr
        headers = dict([ x.split(':') for x in line.split() ])
        data = sys.stdin.read(int(headers['len']))
        write_stderr(data)

        # transition from READY to ACKNOWLEDGED
        write_stdout('RESULT 2\nOK')


        # 使用supervisor的childutils解析
        headers, payload = childutils.listener.wait(sys.stdin, sys.stdout)
        pheaders, pdata = childutils.eventdata(payload + '\n')
        # 當 program 的退出碼爲對應配置中的 exitcodes 值時, expected=1; 否則爲0
        if int(pheaders.get('expected', 1)):
            childutils.listener.ok(sys.stdout)
            continue
        else:  # 0, 異常退出,根據 pheaders 的值發送報警處理
            ############################
            pass  # 你的自定製發送報警邏輯 #
            with open('/opt/sup.log', 'a') as f:  # 這裏寫入文件作爲報警簡單模擬
                f.write(str(pheaders))
                f.write(str(pdata))
                f.write('\n')
            ############################

            # 向 stdout 寫入"RESULT\nOK",並進入下一次循環
            childutils.listener.ok(sys.stdout)

if __name__ == '__main__':
    main()

3、測試

我這邊測試kill -9 可以模擬異常退出

kill pid  # 程序正常退出  expected 退出碼,1

kill -9 pid  # 程序異常退出,expected 退出碼,0

四、常用的事件類型

Event 解釋
PROCESS_STATE 進程狀態發生改變
PROCESS_STATE_STARTING 進程狀態從其他狀態轉換爲正在啓動(Supervisord的配置項中有startsecs配置項,是指程序啓動時需要程序至少穩定運行x秒才認爲程序運行正常,在這x秒中程序狀態爲正在啓動)
PROCESS_STATE_RUNNING 進程從正在啓動狀態轉換爲正在運行狀態
PROCESS_STATE_BACKOFF 進程從正在啓動狀態轉換爲啓動失敗狀態,Supervisor 正在重啓該進程
PROCESS_STATE_STOPPING 進程從正在運行狀態或正在啓動狀態轉換爲正在停止狀態
PROCESS_STATE_EXITED 進程從正在運行狀態轉換爲退出狀態,expected 退出碼,如果是 0 表示進程異常退出,1 表示進程正常退出。
PROCESS_STATE_STOPPED 進程從正在停止狀態轉換爲已停止狀態
PROCESS_STATE_FATAL 進程從啓動失敗狀態(BACKOFF)轉換爲失敗狀態(FATAL). 意味着 startretries 嘗試次數已達上限,Supervisor 已放棄重啓該進程。
PROCESS_LOG 進程產生日誌輸出,被管理的進程需配置,stdout_events_enabled=true or stderr_events_enabled=true 這個事件通知纔會生效。
PROCESS_LOG_STDOUT 進程產生標準輸出,被管理的進程需配置,stdout_events_enabled=true
PROCESS_LOG_STDERR 進程產生錯誤輸出,被管理的進程需配置,stderr_events_enabled=true

參考資料:

http://supervisord.org/events.html

https://blog.51cto.com/tchuairen/2432698

https://lework.github.io/2019/10/16/supervistor-event/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章