Supervisor简介
Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启。它是通过fork/exec的方式把这些被管理的进程当作supervisor的子进程来启动,这样只要在supervisor的配置文件中,把要管理的进程的可执行文件的路径写进去即可。也实现当子进程挂掉的时候,父进程可以准确获取子进程挂掉的信息的,可以选择是否自己启动和报警。supervisor还提供了一个功能,可以为supervisord或者每个子进程,设置一个非root的user,这个user就可以管理它对应的进程。
今天要说的不是supervisor,关于supervisor的使用,百度一大堆,这里不多赘述,今天重点要说的是supervisor事件监控。
Event & Listener
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 的子进程运行。
具体配置实现
配置事件监听器
主管事件侦听器是通过 配置文件中的[eventlistener:x]指定的。关于Supervisor [eventlistener:x] 在配置中允许的键方面,几乎与supervisor [program:x]完全一样,只是Supervisor不遵循事件侦听器进程的“捕获模式”输出(即事件侦听器不能是 PROCESS_COMMUNICATIONS_EVENT事件生成器)。因此,在事件侦听器的配置中指定stdout_capture_maxbytes或 stderr_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
配置监听器脚本。
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()
这里告警的方式可以自己定义,可以邮件,也可以通过webhook调用im接口告警。
实际上supervisor自带有监控利器——superlance。
superlance
superlance是基于supervisor的事件机制实现的一系列命令行的工具集,它实现了许多supervisor本身没有实现的实用的进程监控和管理的特性,包括内存监控,http接口监控,邮件和短信通知机制等。同样的,superlance本身也是使用python编写的。
安装
由于superlance是一个python包,安装起来十分简单,通过easy_install或者pip就可以简单的安装:
easy_install superlance
pip install superlance
当然也可以到github上获得最新的源码(https://github.com/Supervisor/superlance)并安装。
python setup.py install
安装后执行以下httpok命令,如果该命令存在,则说明superlance已经正常安装了。
superlance组件
superlance是一系列命令行工具的集合,其包括以下这些命令:
- httpok 通过定时对一个HTTP接口进行GET请求,根据请求是否成功来判定一个进程是否处于正常状态,如果不正常则对进程进行重启。
- crashmail 当一个进程意外退出时,发送邮件告警。
- memmon 当一个进程的内存占用超过了设定阈值时,发送邮件告警。
- crashmailbatch 类似于crashmail的告警,但是一段时间内的邮件将会被合成起来发送,以避免邮件轰炸。
- fatalmailbatch 当一个进程没有成功启动多次后会进入FATAL状态,此时发送邮件告警。crashmailbatch一样会进行合成报警。
- crashsms 当一个进程意外退出时发送短信告警,这个短信也是通过email网关来发送的。
邮件告警
superlance是使用sendmail来发送邮件的,所以需要安装sendmail。
apt install sendmail
安装完成后配置superlance。
cat /etc/supervisor/conf.d/redis.conf
[program:redis]
command=/usr/local/redis/bin/redis-server /home/redis/etc/redis.conf
directory=/usr/local/redis/bin/
user=redis
autostart = true
autorestart = true
#startsecs = 30
stopwaitsecs = 1
stopsignal = TERM
redirect_stderr = true
[eventlistener:redis_monitor]
command=crashmail -p redis -m xxx@qq.com
events=PROCESS_STATE_EXITED
redirect_stderr=false
首先配置了redis进程启动项目,接着配置了一个名为redis_monitor的事件监听器,它接受来自supervisor的PROCESS_STATE_EXITED事件,并且会触发crashmail的命令行调用。
PROCESS_STATE_EXITED是在一个supervisor的监控项对应的进程意外退出时会触发的事件,这就使得一个进程出现意外退出的情况下会通知到crashmail。
command参数中-p参数配置了crashmail只会对名为redis的监控项作出响应,而-m参数中则配置了崩溃邮件会被发送到的地址。
灵活利用superlance,可以完成各种告警需求,实现各种进程监控。