supervisor的Listeners机制

背景

  • 最近项目需要在容器里添加进程的监控。

配置

  • event listener的配置放置于配置文件中的[eventlistener:x]块中,x是listener的名称,command是执行listener脚本的命令,events是要监控的事件类型。

    1
    2
    3
    [eventlistener:mylistener]
    command=my_custom_listener.py
    events=PROCESS_STATE,TICK_60

事件通知协议

  • 一个event listener可以处于三种状态,ACKNOWLEDGED、READY、BUSY,只有在READY状态下才可以接收事件通知。
    supervisor

  • 一个event listener可以处于三种状态,ACKNOWLEDGED、READY、BUSY,只有在READY状态下才可以接收事件通知。event listener启动时处于ACKNOWLEDGED状态,直到event listener向stdout中输出“READY\n”字符串为止。event listener向stdout中输出“READY\n”之后就处于READY状态,supervisor会向处于READY状态的listener发送listener订阅的事件通知。listener接收事件通知之后就处于BUSY状态,期间listener对接收到的事件通知进行处理,处理结束后向stdout输出“RESULT 2\nOK”或者“RESULT 4\nFAIL”,前者代表处理成功,后者代表处理失败。supervisor收到OK或者FAIL输出后,就将event listener的状态置于ACKNOWLEDGED。FAIL的事件通知会被缓存然后再次发送。event listener的状态处于ACKNOWLEDGED后可以退出执行,也可以继续执行,继续执行就可以向stdout输出“READY\n”形成一个循环。

  • supervisor向listener发送的事件通知由两部分组成,header和body,由”\n”换行符分开。一个header例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    ver:3.0 server:supervisor serial:21 pool:listener poolserial:10 eventname:PROCESS_COMMUNICATION_STDOUT len:54

    ver:协议版本
    server:supervisor的标识符,由[supervisord]块中的identifier选项设置。
    serial:event的序列号
    pool:listener的pool的名字。
    poolserial:event在pool中的的序列号
    eventname:event类型名称
    len:header后面的body长度。
  • 一个body例子:

    1
    2
    3
    4
    5
    6
    processname:foo groupname:bar pid:123
    This is the data that was sent between the tags

    processname:事件所属的子进程名字
    groupname:子进程所属组名
    pid:子进程pid
  • 一个简单的listener脚本,listener.py:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    import sys

    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 True:
    # 进入READY状态
    ┆ write_stdout('READY\n')
    # 读取事件通知的header
    ┆ line = sys.stdin.readline()
    ┆ write_stderr(line)
    # 获取body长度,读取body
    ┆ headers=dict([x.split(':') for x in line.split() ])
    ┆ data = sys.stdin.read(int(headers['len']))
    ┆ write_stderr(data+'\n')
    # 发送OK进入ACKNOWLEDGED状态
    ┆ write_stdout('RESULT 2\nOK')
    if __name__ == '__main__':
    main()
  • 在conf.d目录中建立一个listener配置文件mylistener.conf:

    1
    2
    3
    4
    5
    6
    7
    [eventlistener:mylistener]
    command=python listener.py
    directory=/thedirectoroflistener.py
    user=user
    events=PROCESS_STATE,TICK_5
    stdout_logfile=/path/to/mylistener_stdout.log
    stderr_logfile=/path/to/mylistener_stderr.log
  • 启动以后,监控就开始了,可以到日志中查看事件通知的内容如下,可以根据自己的需要设定监控的事件类型,然后根据不同的事件类型和内容做出不同的应变,具体的事件类型可以官网查看。

    1
    2
    3
    4
    5
    6
    ver:3.0 server:supervisor serial:15361 pool:mylistener poolserial:15361 eventname:PROCESS_STATE_RUNNING len:73
    processname:mylistener groupname:mylistener from_state:STARTING pid:87728
    ver:3.0 server:supervisor serial:15362 pool:mylistener poolserial:15362 eventname:TICK_5 len:15
    when:1514313560
    ver:3.0 server:supervisor serial:15364 pool:mylistener poolserial:15364 eventname:PROCESS_STATE_RUNNING len:73
    processname:celerybeat groupname:celerybeat from_state:STARTING pid:87729
-------------本文结束感谢您的阅读-------------

许可协议: 署名-非商业性使用 转载请保留原文链接及作者。