Supervisor 的使用和進階 (4) - supervisor Event 的使用

本文主要介紹 supervisor Event 的功能。html

supervisor 做爲一個進程管理工具,在 3.0 版本以後,新增了 Event 的高級特性, 主要用於作(進程啓動、退出、失敗等)事件告警服務。

Event 特性是將監聽的服務(listener)註冊到supervisord中,當supervisord監聽到相應事件時,將事件信息推送給監聽對應事件的listener。golang

事件類型

Event 能夠設置 27 種事件類型,能夠分爲以下幾類:工具

1. 監控進程狀態轉移事件;
2. 監控進程狀態日誌變動事件;
3. 進程組中進程添加刪除事件;
4. supervisord 進程自己日誌變動事件;
5. supervisord 進程自己狀態變動的事件;
6. 定時觸發事件。

事件能夠被單獨監聽,也能夠一個listener 監聽多種事件。spa

配置說明

對於一個listener,與正常program的區別是,新增了events 參數,用於標識要監聽的事件。日誌

[eventlistener:theeventlistenername]
events=PROCESS_STATE,TICK_60 
buffer_size=10 ; 事件池子大小(輸入流大小)

事件類型配置多個,用逗號分割。上述配置的是子進程狀態的變動,以及定時60s通知間隔60s
事件通知緩衝區大小,能夠自定義配置,上述配置了10個事件消息的緩衝。code

Listener 的實現

與supervisord 的交互

因爲supervisord 是 listener的父進程,因此交互方式採用最簡單的 標準輸入輸出的方式交互。listener 經過標準輸入獲取事件,經過標準輸出通知supervisord listener的事件處理結果,以及當前supervisord的狀態server

listener 的狀態

listener 有三種狀態:ACKNOWLEDGED、READY、BUSY.htm

  • ACKNOWLEDGED: listener 未就緒的狀態。(發送READY以前的狀態)
  • READY: 等待事件觸發的狀態。(發送READY 消息後,未收到消息的狀態)
  • BUSY: 事件處理中的狀態。(即輸出 OK, FAIL 以前處理Event消息時的狀態)

supervisor_listener_status.jpg

消息協議

消息包括supervisord 通知給listener 的事件消息和 listener 通知給supervisord 的狀態變動消息。blog

listener 的狀態變動消息, READYtoken

  • 狀態OK的 "READYn" 消息
  • 處理成功 "RESULT 2nOK" 消息
  • 處理失敗 "RESULT 4nFAIL" 消息

supervisord 廣播的事件消息, 事件消息分爲 header 和 payload 兩部分。 header 中採用kv的方式發送,header 中包含了 payload 的長度。

例如官網提供的header 的例子:

ver:3.0 server:supervisor serial:21 pool:listener poolserial:10 eventname:PROCESS_COMMUNICATION_STDOUT len:54

header 含義:

  • serial 爲事件的序列號
  • pool 表示listener 的進程池名稱(listener支持啓動多個)
  • poolserial 表示listener的進程池序列號
  • eventname 事件名稱
  • len body 的長度

Listener 的基本流程

listener 的處理流程以下:

1. 發送ready消息,等待事件發生。
2. 收到事件後,處理事件
3. 事件處理完成後,發送 result 消息, 從第一步開始循環

進程狀態轉移舉例

咱們以進程狀態轉移做爲例子,作簡單介紹。

首先,使用 golang 實現listener

package main

import (
    "bufio"
    "os"
    "strconv"
    "strings"
)

const RESP_OK = "RESULT 2\nOK"
const RESP_FAIL = "RESULT 4\nFAIL"

func main() {
    stdin := bufio.NewReader(os.Stdin)
    stdout := bufio.NewWriter(os.Stdout)
    stderr := bufio.NewWriter(os.Stderr)

    for {    
        // 發送後等待接收event
        _, _ = stdout.WriteString("READY\n")
        _ = stdout.Flush()
        // 接收header
        line, _, _ := stdin.ReadLine()          
        stderr.WriteString("read" + string(line))
        stderr.Flush()

        header, payloadSize := praseHeader(line)

        // 接收payload
        payload := make([]byte, payloadSize)
        stdin.Read(payload)   
        stderr.WriteString("read : " + string(payload))
        stderr.Flush()

        result := alarm(header, payload)

        if result {   // 發送處理結果
            stdout.WriteString(RESP_OK)
        } else {
            stdout.WriteString(RESP_FAIL)
        }
        stdout.Flush()
    }
}

func praseHeader(data []byte) (header map[string]string, 
        payloadSize int) {
    pairs := strings.Split(string(data), " ")
    header = make(map[string]string, len(pairs))

    for _, pair := range pairs {
        token := strings.Split(pair, ":")
        header[token[0]] = token[1]
    }

    payloadSize, _ = strconv.Atoi(header["len"])
    return header, payloadSize
}

// 這裏設置報警便可
func alarm(header map[string]string, payload []byte) bool {
    // send mail
    return true
}

這裏,報警處理未填寫。

其次,在supervisor 中添加配置,監聽服務:

[eventlistener:listener]
command=/root/listener
events=PROCESS_STATE,TICK_5
stdout_logfile=/var/log/tmp/listener_test_stdout.log
stderr_logfile=/var/log/tmp/listener_test_stderr.log
user=root

這裏監聽了服務的處理狀態,以及每5s的心跳消息。

最後,啓動listener。

supervisorct start listener

從stderr的日誌中能夠看到,簡單的TICK_5 的消息(調整了格式):

header : ver:3.0 server:supervisor serial:256 pool:listener_test poolserial:173 eventname:TICK_5 len:15read 
payload: when:1586258030

fastcgi 進程狀態變動的消息:

header : ver:3.0 server:supervisor serial:291 pool:listener_test poolserial:208 eventname:PROCESS_STATE_EXITED len:87
payload: processname:fastcgi_test groupname:fastcgi_test from_state:RUNNING expected:0 pid:19119

header :ver:3.0 server:supervisor serial:293 pool:listener_test poolserial:210 eventname:PROCESS_STATE_STARTING len:73
payload: processname:fastcgi_test groupname:fastcgi_test from_state:EXITED tries:0

events 參考

weixin_logo.png

相關文章
相關標籤/搜索