erlang学习笔记之用OTP构建系统4

监控树 supervisor

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

1,Supervision原则(重点)


supervisor负责启动、停止和监控它的子进程
supervisor在必要时通过重启它的子进程来保持它们活着
supervisor的子被定义为一个子规范的list
当supervisor启动时,子进程按list从左至右的顺序启动
当supervisor终止时,它首先按启动顺序的反顺序终止它的子进程

2,例子
-module(ch_sup).
-behaviour(supervisor).

-export([start_link/0]).
-export([init/1]).

start_link() ->
  supervisor:start_link(ch_sup, []).

init(_Args) ->
  {ok, {{one_for_one, 1, 60},
    [{ch3, {ch3, start_link, []},
      permanent, brutal_kill, worker, [ch3]}]}}.

one_for_one是重启策略之一
1和60定义了最大重启频率
tuple {ch3, …}是子规范

3,重启策略


3.1 one_for_one
如果一个子进程停止,则只重启该进程

3.2 one_for_all
如果一个子进程停止,所有其他子进程也停止,然后所有进程重启

3.3 rest_for_one
如果一个子进程停止,则启动顺序中在它之后的所有其他子进程也停止,然后停止的这些进程重启(跟楼上那位不一样)
3.4 simple_one_for_one
一个简化的one_for_one supervisor,所有的子进程都是同样进程类型并且是动态添加的实例

4,最大重启频率
init(...) ->
  {ok, {{RestartStrategy, MaxR, MaxT},
    [ChildSpec, ...]}}.


supervisor有一个自带的机制来限制给定时间内重启的次数
这是通过MaxRMaxT这两个参数来决定的

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

5,子规范
Module = atom()
{Id, StartFunc, Restart, Shutdown, Type, Modules}
  Id = term()
  StartFunc = {M, F, A}
    M = F = atom()
    A = [term()]
  Restart = permanent | transient | temporary
  Shutdown = brutal_kill | integer() >=0 | infinity
  Type = worker | supervisor
  Modules = [Module] | dynamic
    Module = atom()

Id是用来让supervisor内部识别子规范的名字


StartFunc定义了用来启动子进程的的方法,符合module-function-arguments tuple{M, F, A}
它应该调用supervisor:start_link,gen_server:start_link,gen_fsm:start_link或gen_event:start_link,或相适应的方法

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


Shutdown定义了子进程怎样终止
1)brutal_kill表示子进程使用exit(Child, kill)来无条件的终止


2)一个整数timeout值表示supervisor告诉子进程通过调用exit(Child, shutdown)来终止,然后等待一个exit信号返回
如果没有在指定的时间内接收到exit信号,则子进程使用exit(Child, kill)来无条件的终止


3)如果子进程是另一个supervisor,它应该设置为infinity来给子树足够的时间来终止
Type指定子进程是一个supervisor还是一个worker
Modules应该是一个list,含有一个元素[Module]
如果子进程是一个supervisor,gen_server或gen_fsm则Module是callback模块的名字
如果子进程是一个gen_event,则Modules应该为dynamic
该信息用来在升级和降级时供release handler使用
例子:启动服务器ch3的子规范

{ch3,
  {ch3, start_link, []},
  permanent, brutal_kill, worker, [ch3]}

例子:启动event manager的子规范

{error_man,
  {gen_event, start_link, [{local, error_man}]},
  permanent, 5000, worker, dynamic}

服务器和event manager都是注册进程,可以在任何时候访问,这样它们都指定为permanent
ch3不需要在终止之前做任何清理工作,这样就不需要timeout,但是必须满足brutal_kill,error_man可能需要一些时间来让event handler清理,这样Shutdown设置为5000ms
例子:启动另一个supervisor的子规范

{sup,
  {sup, start_link, []},
  transient, infinity, supervisor, [sup]}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值