Supervisor默认提供了一套基于事件监听的事件通知机制,以便你可以在Supervisor发生某个你感兴趣的事件时,你可以收到通知,然后做出相应的操作:
-
当某个进程占用内存太多,你可能需要重启它;
-
当某个事件监听器的队列池pool里的工作event listener总是很繁忙(满负荷在工作),这时你可能需要根据情况多增加一些eventlistener子进程数。
-
当某个进程奔溃并由supervisor重启后,你可能希望通过电子邮件通知某人。
注意:
-
默认情况下,不管你是否设置相应的事件监听器去监听特定的Supervisor里面的事件,Supervisor都会对里面发生的事件触发事件通知,只是没有任何该事件对应的监听器的时候,就相当于没有没有被任何监听器处理罢了。
-
Supervisor会把事件通知预先按不同的事件类型进行分组,以使后面的事件监听器能够根据指定的事件类型来订阅感兴趣的事件通知。
1. Supervisor架构
1.1. Supervisor管理进程的示意图
- 默认情况下,除非通过[group:groupname] 部分明显了指定程序分组,不然Supervisor就会为每一个未显示指明分组的子进程创建一个与[program:processname]的processname同名的分组,并将该进程的所有子进程都放进这个创建的分组中进行统一管理。每一个[program:groupname]部分所能生成的子进程个数由其下定义的numprocs指定。
- 对于每一个由[eventlistener:listenername]定义的事件监听器,Supervisor也会根据其他的numprocs的值生成一个包含numprocs个子事件监听器进程的事件监听器池Pool。
1.2. Supervisor所管理的子进程的状态流转示意图
- 处于BACKOFF状态的进程会被Supervisor自动重启,所以该进程会在STARTING和BACKOFF之间切换,直到Supervisor重试了startretries次之后还未成功就会把该进程的状态切换为FATAL状态。
- 如果autorestart=true,则处于EXISTED状态的进程会被Supervisor自动重启;如果autorestart=unexpected,如若该进程的退出码不在exitcode定义的范围内,则会被Supervisor自动重启。
- 处于FATAL状态的进程不会被Supervisor自动重启。
- 如果一个进程一直卡在STOPPING状态,则可能进程已经卡死了,这时候需要你手动强制操作来停止该进程了。
- 以下的状态转换需要用户手动操作:
FATAL->STARTING
RUNNING -> STOPPING
1.3. Supervisor的事件通知示意图
此示意图可以在第四章节查看详细
1.4. Capture Mode捕获模式
1.4.1 Capture Mode的工作原理
当一个进程stream流进入capture mode捕获模式时,发送到stream中数据会被发送到一个独立的内存存储的“capture buffer”中(这个capture buffer的大小由配置文件中最大的capture_bytes决定。当这个capture buffer中的数据大小超过capture_bytes时,最早(旧)的数据会丢弃以给新的数据腾挪出空间。
当一个进程stream流退出capture mode捕获模式时,supervisor就会触发一个PRCESS_COMMUNICATION事件的子类型,该子类型可能会被配置文件中指定的某个事件监听器拦截(处理)。
1.4.2. 如何开启捕获模式?
需要在对应的子程序配置[program:x]部分,指明一下两个参数之一(设置非0值),示例如下:
stdout_capture_maxbytes=30kb
stderr_capture_maxbytes=30kb
启用上面的设置后才会在该子程序的进程的stdout或stderr中输出特殊的tokens数据,才能有效的引起supervisor去触发一个PROCESS_COMMUNICATION事件。
》注意只有[program:x]中定义的进程才能拥有Capture Mode的定义,而[eventlistener:x]这个是作为事件监听器的主要进程主体,是无法进入Capture Mode,即事件监听器不能是PROCESS_COMMUNICATION事件生成器(不然死循环)。
1.4.3. Supervisor的进程通讯协议的数据结构
Supervisor的进程通讯协议依赖2个标签
- 开始标签<!—XSUPERVISOR:BEGIN—>
- 命令supervisor进入stream流的捕获模式“capture mode”
- 结束标签<!—XSUPERVISOR:END—>
- 一个标签命令supervisor退出stream流的捕获模式
其中为了上面这两个标签之间的数据可以是随意,这个数据会构成PROCESS_COMMUNICATION事件的payload。示例:
<!--XSUPERVISOR:BEGIN-->Hello!<!--XSUPERVISOR:END-->
其中在开始和结束标签之间的数据就是Event的Payload内容:Hello!
2. 事件通知的数据结构
当supervisord向事件侦听器进程发送通知时,会首先在该选中的事件监听器的stdin上发送一个“Header”行。然后在Header换行之后紧接的就是事件payload(该payload可能有多行)。
示例如下:其中第1行为Header行,剩下的数据行为事件Payload。
ver:3.0 server:supervisor serial: