【整理】Erlang 中的 supervisor

简介:

【概况】

supervisor behaviour 是用来实现监控其他子进程的 supervisor 进程的模块;  
子进程可以是另一个 supervisor 进程,也可以是一个 worker 进程;  
worker 进程一般使用 gen_event,gen_fsm 或 gen_server behaviour 来实现    
一个使用 supervisor behaviour 实现的 supervisor 有一个接口方法的标准集,包括跟踪和错误报告的功能;  
supervisor 机制用来构建一个分层进程结构,称为 supervision tree,这是组织一个容错系统的好方式。  

【原则】

supervisor 负责启动、停止和监控它的子进程;  
supervisor 在必要时,通过重启它的子进程来使其保持活着;  
supervisor 的子进程由称作子进程规范的列表进行定义;  
当 supervisor 启动时,子进程按子进程规范列表中内容从左至右的顺序启动;  
当 supervisor 终止时,会按子进程启动顺序的反顺序终止相应子进程。  

【重启策略】

one_for_one  
如果一个子进程停止,则只重启该子进程;  
one_for_all  
如果一个子进程停止,则所有其他子进程也停止,然后所有子进程重启;  
rest_for_one  
如果一个子进程停止,则启动顺序中在它之后的所有其他子进程也停止,然后停止的这些子进程重启;  
simple_one_for_one   
一个简化的 one_for_one ,所有的子进程都是同样进程类型并且是动态添加的实例;  

【最大重启频率】

supervisor 有一个自带的机制来限制给定时间内重启的次数;  
如果在最近的 MaxT 秒之内有超过 MaxR 次数的重启,则 supervisor 停止它本身和它所有的子进程;  
当 supervisor 停止后,下一个更高级别的 supervisor 将进行下一步动作,重启上述停止的 supervisor 或者终止本身;  
重启机制的意图是防止一个进程由于某些原因重复性的死掉;  

【子规范】

?
1
{Id, StartFunc, Restart, Shutdown, Type, Modules}
Id   用于 supervisor 内部识别子规范的名字;  

StartFunc   定义了用来启动子进程的的方法,由三元组 {M, F, A} 来确定,其一般情况下调用的是  supervisor:start_link     gen_server:start_link   gen_fsm:start_link   或  gen_event:start_link   ,或对上述函数的相应封装。   

Restart   定义了子进程什么时候重启:  
  • permanent 表示子进程始终重启;
  • temporary 表示子进程决不重启;
  • transient 表示只有在子进程异常终止时才重启,即除了 normal 以外的终止原因;

Shutdown   定义了子进程怎样终止:  
  • brutal_kill 表示子进程使用 exit(Child, kill) 来无条件的终止;
  • 一个整数 timeout 值表示 supervisor 通过调用 exit(Child, shutdown) 告诉子进程请终止自己,然后等待子进程返回退出信号;如果没有在指定的时间内接收到(来自子进程的) 退出信号,则使用 exit(Child, kill) 无条件终止子进程
  • 如果子进程是另一个 supervisor,则应该设置为 infinity 来给子树足够的时间来终止;

Type   指定子进程是一个 supervisor 还是一个 worker;  

Modules   应该是一个 list,含有一个元素 [Module]。  
如果子进程是一个 supervisor,或者子进程是 woker 且采用 gen_server 或 gen_fsm 行为模式实现,则 Modules 是 callback 模块的名字;  
如果子进程是 worker 且采用 gen_event 行为模式实现,则 Modules 应该为  dynamic   ,该信息用来在升级和降级时供 release handler 使用;  

【参数选择原则】

按照子进程规范启动的子进程,若是要求该子进程为任何时候均可访问的注册进程,则一般使用参数 permanent ;  
按照子进程规范启动的子进程,若是要求该子进程终止之前不需要做任何清理工作,则不需要设置 timeout 值,可以设置为 brutal_kill  
若是要求其终止之前做相应资源清理,则需要设置 timeout 超时值。   

【启动 supervisor】

?
1
supervisor:start_link(CallbackModuleName, InitCallbackParamList).
启动一个新的 supervisor 进程并链接到 OTP 系统的监督树中;  
  • 第一个参数 callback 模块的名字,是 init callback 方法所在 module 的名字;
  • 第二个参数 init callback 方法的参数列表;
supervisor 的执行流程如下:  
supervisor:start_link  --> init --> 根据指定的子规范的入口来启动它的所有子进程  

注意   supervisor:start_link 是同步的,当所有子进程启动之后才会返回    

【动态添加子进程】

?
1
supervisor:start_child(Sup, ChildSpec)
Sup 是 supervisor 的 pid 或名字,ChildSpec 是子进程规范;  
使用 supervisor:start_child/2 添加的子进程会表现出像其他子进程一样的行为,除了这点,如果 supervisor 死掉然后重启,则所有动态添加的子进程都将丢失  

【停止一个子进程】

任何子进程,不管静态的还是动态的,都可以使用 shutdown 规范来停止。  
?
1
supervisor:terminate_child(Sup, Id)
停止的子进程的子规范使用如下调用来删除。  
?
1
supervisor:delete_child(Sup, Id)
Sup 是 supervisor 的 pid 或 name,Id 是子规范里指定的 id 。  
就像动态添加的子进程一样,如果 supervisor 本身重启,那么删除静态子进程的效果会丢失  

【simple_one_for_one】

采用 simple_one_for_one 重启策略的 supervisor 是一个简化的 one_for_one supervisor,所有的子进程都是动态添加的同一类型子进程的实例。  
?
1
2
3
4
5
6
7
8
9
10
11
12
13
-module(simple_sup).
-behaviour(supervisor).
 
- export ([start_link /0 ]).
- export ([init /1 ]).
 
start_link() ->
   supervisor:start_link(simple_sup, []).
 
init(_Args) ->
   {ok, {{simple_one_for_one, 0, 1},
     [{call, {call, start_link, []},
       temporary, brutal_kill, worker, [call]}]}}.
当 supervisor 通过 supervisor:start_link/2 启动后,将不会启动任何子进程,而是通过调用如下代码来动态添加子进程:  
?
1
supervisor:start_child(Sup, List)
Sup 是 supervisor 的 pid 或 name,List 是一个任意的 term 列表,该列表值将会被动态添加到子规范的参数列表里;  
如果启动方法指定为 {M, F, A},则子进程的启动是通过调用 apply(M, F, A++List) 来完成的。   

【supervisor 的终止】

既然 supervisor 是 supervision tree 的一部分,则其将自动被它自身的 supervisor 所终止;当终止时,它会按启动的反顺序根据相应的 shutdown 规范来自动终止它所有的子进程,然后终止本身。  
目录
相关文章
|
11月前
|
监控 网络协议 Unix
Supervisor的简单使用
Supervisor的简单使用
74 0
Supervisor的简单使用
|
10月前
|
监控 程序员 Linux
supervisor的正确离线安装和使用
supervisor的正确离线安装和使用
349 0
|
监控 Ubuntu Python
Supervisor离线安装及使用
Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启。它是通过fork/exec的方式把这些被管理的进程当作supervisor的子进程来启动,这样只要在supervisor的配置文件中,把要管理的进程的可执行文件的路径写进去即可。也实现当子进程挂掉的时候,父进程可以准确获取子进程挂掉的信息的,可以选择是否自己启动和报警
169 0
|
监控 Unix 程序员
正确离线安装supervisor
supervisor是一个用python语言编写的进程管理工具,它可以很方便的监听、启动、停止、重启一个或多个进程。当一个进程意外被杀死,supervisor监听到进程死后,可以很方便的让进程自动恢复,不再需要程序员或系统管理员自己编写代码来控制。
468 0
|
JavaScript
supervisor安装
supervisor安装
110 0
|
存储 监控 程序员
《supervisor.erl 源码解读》
erlang程序员研究OTP,如同C++程序员研究STL一样重要。
《supervisor.erl 源码解读》
|
监控 Ubuntu Shell
supervisor简介、安装与入门使用
supervisor简介、安装与入门使用
298 0