进程管理工具Supervisor(二)Events
supervisor可以当做一个简单的进程启动、重启、控制工具使用,也可以作为一个进程监控框架使用,作为后者,需要使用supervisor的Events机制。
Event Listeners
supervisor对子程序的监控通过叫做event listener的程序实现。supervisor控制的子程序状态发生变化时,就会产生一些事件通知,event listener可以对这些事件通知进行订阅。
event listener本身也是作为supervisor的子程序运行的。事件通知协议的实现基于event listener子程序的stdin和stdout。supervisor发送特定格式的信息到event listener的stdin,然后从event listener的stdout获得特定格式的输出,从而形成一个请求/应答循环。
配置
event listener的配置放置于配置文件中的[eventlistener:x]块中。
[eventlistener:mylistener]
command=my_custom_listener.py
events=PROCESS_STATE,TICK_60
x是listener的名称,command是执行listener脚本的命令,events是要监控的事件类型。
event listener本身是作为supervisor的子程序运行的,所以与配置子程序[program:x]块类似,官网例子:
[eventlistener:theeventlistenername]
command=/bin/eventlistener
process_name=%(program_name)s_%(process_num)02d
numprocs=5
events=PROCESS_STATE
buffer_size=10
directory=/tmp
umask=022
priority=-1
autostart=true
autorestart=unexpected
startsecs=1
startretries=3
exitcodes=0,2
stopsignal=QUIT
stopwaitsecs=10
stopasgroup=false
killasgroup=false
user=chrism
redirect_stderr=false
stdout_logfile=/a/path
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=10
stdout_events_enabled=false
stderr_logfile=/a/path
stderr_logfile_maxbytes=1MB
stderr_logfile_backups=10
stderr_events_enabled=false
environment=A="1",B="2"
serverurl=AUTO
事件通知协议
一个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例子:
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例子:
processname:foo groupname:bar pid:123
This is the data that was sent between the tags
processname:事件所属的子进程名字
groupname:子进程所属组名
pid:子进程pid
一个简单的listener脚本,listener.py:
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:
[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
启动:
ubuntu:$ sudo supervisorctl start all
mylistener: started
celerybeat: started
ubuntu:$ sudo supervisorctl status
celerybeat RUNNING pid 87729, uptime 0:00:20
mylistener RUNNING pid 87728, uptime 0:00:20
监控就开始了,可以到日志中查看事件通知的内容:
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
可以根据自己的需要设定监控的事件类型,然后根据不同的事件类型和内容做出不同的应变,具体的事件类型可以官网查看。
python的supervisor.childutils模块对header和body的处理进行了包装:
def get_headers(line):
return dict([ x.split(':') for x in line.split() ]) def eventdata(payload):
headerinfo, data = payload.split('\n', 1)
headers = get_headers(headerinfo)
return headers, data def get_asctime(now=None):
if now is None: # for testing
now = time.time() # pragma: no cover
msecs = (now - long(now)) * 1000
part1 = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(now))
asctime = '%s,%03d' % (part1, msecs)
return asctime class ProcessCommunicationsProtocol:
def send(self, msg, fp=sys.stdout):
fp.write(ProcessCommunicationEvent.BEGIN_TOKEN)
fp.write(msg)
fp.write(ProcessCommunicationEvent.END_TOKEN) def stdout(self, msg):
return self.send(msg, sys.stdout) def stderr(self, msg):
return self.send(msg, sys.stderr) pcomm = ProcessCommunicationsProtocol() class EventListenerProtocol:
def wait(self, stdin=sys.stdin, stdout=sys.stdout):
self.ready(stdout)
line = stdin.readline()
headers = get_headers(line)
payload = stdin.read(int(headers['len']))
return headers, payload def ready(self, stdout=sys.stdout):
stdout.write(PEventListenerDispatcher.READY_FOR_EVENTS_TOKEN)
stdout.flush() def ok(self, stdout=sys.stdout):
self.send('OK', stdout) def fail(self, stdout=sys.stdout):
self.send('FAIL', stdout) def send(self, data, stdout=sys.stdout):
resultlen = len(data)
result = '%s%s\n%s' % (PEventListenerDispatcher.RESULT_TOKEN_START,
str(resultlen),
data)
stdout.write(result)
stdout.flush() listener = EventListenerProtocol()
listener脚本可以方便的写做:
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 True:
┆ headers, payload = childutils.listener.wait()
┆ write_stderr(payload+'\n')
┆ childutils.listener.ok(sys.stdout) if __name__ == '__main__':
main()
进程管理工具Supervisor(二)Events的更多相关文章
- 进程管理工具supervisor
1. 简介 supervisor有两个组件:supervisord和supervisorctl,组成了client/server结构. supervisord负责读入配置文件,然后supervisor ...
- Linux进程管理工具Supervisor的安装配置
目录 Linux进程管理工具Supervisor的安装配置 简介 安装Python包管理工具 安装Supervisor 配置 配置文件参数说明 配置进程管理 启动supervisor 控制进程 交互终 ...
- Python 进程管理工具 Supervisor 使用教程
Supervisor 是基于 Python 的进程管理工具,只能运行在 Unix-Like 的系统上,也就是无法运行在 Windows 上.Supervisor 官方版目前只能运行在 Python 2 ...
- Linux进程管理工具——supervisor
介绍 Supervisord是用Python实现的一款非常实用的进程管理工具 安装 这里用源码 supervisor-.tar.gz .tar.gz cd supervisor- sudo pytho ...
- linux 使用进程管理工具 supervisor
1.supervisor是使用python进行开发的运行在linux服务器上的进程管理工具 老版本的supervisor需要运行在python2环境,如果需要使用supervisor管理python3 ...
- python进程管理工具Supervisor
一.Supervisor简单介绍 supervisor是一个 Client/Server模式的系统,允许用户在类unix操作系统上监视和控制多个进程,或者可以说是多个程序.supervisor与lau ...
- 进程管理工具Supervisor(一)简介与使用
Supervisor是用Python开发的一套client/server架构的进程管理程序,能做到开机启动,以daemon进程的方式运行程序,并可以监控进程状态等等. linux进程管理方式有传统的r ...
- 进程管理工具 Supervisor
要想在终端后台常驻进程,首先想到的是在命令后加 & 符号,来达到隐藏程序在后台的目的,尽管看起来进程已经在后台运行了,实际上终端会话关闭时进程还是会被 kill 掉,这种问题一般是采用搭配 n ...
- Linux进程管理工具Supervisor
简述 Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启. 它是通过fork/exec的方式把这些被管 ...
随机推荐
- 利用KindEditor实现公司通讯录的维护
引言: 本人所属施工单位,在建项目较多,通讯录是以项目为单位挂接在公司内部网站通讯录板块,以静态页面展示.一直以来都是项目部办公室通过电话.邮件等方式通知总部信息部门变更通讯录,日常维护的工作量较大. ...
- Windows下编译nginx-rtmp-module
http://nginx.org/en/docs/howto_build_on_win32.html 官网上的操作说明. 官网的方法Nginx编译方法,思路是一致的,只是有几个细节地方需要调整. 需要 ...
- springMVC(1)---获取前段数据
springMVC(1)---获取前段数据 首先说明,如果你学过Struts2,那么在学springMVC就会简单很多,我也不最基础的开始写了,我前篇文章搭建了个ssm框架,算是springmvc入门 ...
- iOS旋钮动画-CircleKnob
欢迎相同喜欢动效的project师/UI设计师/产品添加我们 iOS动效特攻队–>QQ群:547897182 iOS动效特攻队–>熊熊:648070256 前段时间和群里的一个设计师配合. ...
- DocFX生成PDF文档
使用DocFX生成PDF文档,将在线文档转换为PDF离线文档. 关于DocFX的简单介绍使用DocFX生成文档 使用docfx 命令 1.下载 https://github.com/dotnet/do ...
- 微服务架构之RPC-client序列化细节
通过上篇文章的介绍,知道了要实施微服务,首先要搞定RPC框架,RPC框架的职责要向[调用方]和[服务提供方]屏蔽各种复杂性: (1)让调用方感觉就像调用本地函数一样 (2)让服务提供方感觉就像实现一个 ...
- select的限制以及poll的使用
1.先说select在多路IO中的限制:1)linux中每个程序能够打开的最多文件描述符是有限制的.默认是1024.可以通过ulimit -n进行查看和修改: xcy@xcy-virtual-mach ...
- 【转载】Android Studio 导入External Libraries
转载: 世军 Android Studio 导入External Libraries http://www.cnblogs.com/shijunzhang/p/5625432.html 导入本地Li ...
- springboot 热部署的两种方式
问题的提出: 在编写代码的时候,你会发现我们只是简单把打印信息改变了,就需要重新部署,如果是这样的编码方式,那么我们估计一天下来就真的是打几个Hello World就下班了.那么如何解决热部署的问题呢 ...
- ES6原生Promise的所有方法介绍(附一道应用场景题目)
JS的ES6已经出来很久了,作为前端工程师如果对此还不熟悉有点说不过去.不过如果要问,Promise原生的api一共有哪几个?好像真的可以难倒一票人,包括我自己也忽略了其中一个不常用的API Prom ...