【转】erlang四种监控策略one_for_one、one_for_all、simple_one_for_one、rest_for_one

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

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

2,例子 
启动服务器的supervisor的callback模块:

Java代码  

  1. -module(ch_sup).
  2. -behaviour(supervisor).
  3. -export([start_link/0]).
  4. -export([init/1]).
  5. start_link() ->
  6. supervisor:start_link(?MODULE, []).
  7. init(_Args) ->
  8. {ok, {{one_for_one, 1, 60},
  9. [{ch3, {ch3, start_link, []},
  10. 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,最大重启频率 
supervisor有一个自带的机制来限制给定时间内重启的次数 
这是通过MaxR和MaxT这两个参数来决定的

Java代码  

  1. init(...) ->
  2. {ok, {{RestartStrategy, MaxR, MaxT},
  3. [ChildSpec, ...]}}.

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

5,子规范 
这是子规范的类型定义:

Java代码  

  1. {Id, StartFunc, Restart, Shutdown, Type, Modules}
  2. Id = term()
  3. StartFunc = {M, F, A}
  4. M = F = atom()
  5. A = [term()]
  6. Restart = permanent | transient | temporary
  7. Shutdown = brutal_kill | integer() >=0 | infinity
  8. Type = worker | supervisor
  9. Modules = [Module] | dynamic
  10. 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的子规范

Java代码  

  1. {ch3,
  2. {ch3, start_link, []},
  3. permanent, brutal_kill, worker, [ch3]}

例子:启动event manager的子规范

Java代码  

  1. {error_man,
  2. {gen_event, start_link, [{local, error_man}]},
  3. permanent, 5000, worker, dynamic}

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

Java代码  

  1. {sup,
  2. {sup, start_link, []},
  3. transient, infinity, supervisor, [sup]}

6,启动一个supervisor 
上面的例子通过调用ch_sup:start_link()来启动supervisor:

Java代码  

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

ch_sup:start_link调用方法supervisor:start_link/2,这个方法启动一个新的supervisor进程并连接它 
1)第一个参数ch_sup是callback模块的名字,它是init callback方法所在的位置 
2)第二个参数[]是传给init callback方法的参数 
一个supervisor进程调用callback方法ch_sup:init([]),返回{ok, StateSpec}:

Java代码  

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

然后根据指定的子规范的入口来启动它的所有子进程,在这里有一个子进程ch3 
注意supervisor:start_link是同步带,当作有子进程启动之后才会返回

7,添加一个子进程 
除了静态的supervision tree,我们也可以添加动态子进程到已有的supervisor里:

Java代码  

  1. supervisor:start_child(Sup, ChildSpec)

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

8,停止一个子进程 
任何子进程,不管静态的还是动态的,都可以使用shutdown规范来停止:

Java代码  

  1. supervisor:terminate_child(Sup, Id)

停止的子进程的子规范使用如下调用来删除:

Java代码  

  1. supervisor:delete_child(Sup, Id)

Sup是supervisor的pid或name,Id是子规范里指定的id 
就像动态添加的子进程一样,如果supervisor本身重启,那么删除静态子进程的效果会丢失

9,simple_one_for_one supervisor 
simple_one_for_one重启策略的supervisor是一个简化的one_for_one supervisor,所有的子进程都是动态添加的同一进程的实例 
一个simple_one_for_one supervisor callback模块的例子:

Java代码  

  1. -module(simple_sup).
  2. -behaviour(supervisor).
  3. -export([start_link/0]).
  4. -export([init/1]).
  5. start_link() ->
  6. supervisor:start_link(simple_sup, []).
  7. init(_Args) ->
  8. {ok, {{simple_one_for_one, 0, 1},
  9. [{call, {call, start_link, []},
  10. temporary, brutal_kill, worker, [call]}]}}.

当启动后,supervisor将不会启动任何子进程,而是通过调用如下代码来动态添加所有的子进程:

Java代码  

  1. supervisor:start_child(Sup, List)

Sup是supervisor的pid或name,List是一个任意的term列表,将会被动态添加到子规范的参数列表里 
如果启动方法指定为{M, F, A},则子进程通过调用apply(M, F, A++List)来启动 
例如,添加一个子进程到simple_sup:

Java代码  

  1. supervisor:start_child(Pid, [id1])

这将会通过调用apply(call, start_link, []++[id1])即call:start_link(id1)来启动子进程

10,终止 
既然supervisor是supervision tree的一部分,则它将自动被它的supervisor终止 
当终止时,它会按启动的反顺序根据相应的shudown规范来自动终止它所有的子进程,然后终止本身

补充:supervisor exports and callbacks

Java代码  

    1. supervisor module                  Callback module
    2. supervisor:start_link              Module:init/1
    3. supervisor:start_child
    4. supervisor:terminate_child
    5. supervisor:delete_child
    6. supervisor:restart_child
    7. supervisor:which_children
    8. supervisor:check_childspecs

原文地址:http://jasionq.blog.163.com/blog/static/10970577920133883158424/

时间: 2024-08-01 10:45:25

【转】erlang四种监控策略one_for_one、one_for_all、simple_one_for_one、rest_for_one的相关文章

erlang四种监控策略

转自:http://jasionq.blog.163.com/blog/static/10970577920133883158424/ Supervisor Behaviour是一个用来实现一个supervisor进程来监控其他子进程的模块 子进程可以是另一个supervisor,也可以是一个worker进程 worker进程一般使用gen_event,gen_fsm或gen_server behaviour来实现 一个使用该模块来实现的supervisor有一个接口方法的标准集,包括跟踪和错误

Hibernate 原汁原味的四种抓取策略(转)

原文出处:http://www.cnblogs.com/rongxh7/archive/2010/05/12/1733088.html     尊重原作者,访问原创地址 最近在研究 Hibernate 的性能优化的时候碰到了"抓取策略", 由于以前没有详细的研究过, 所以到处找资料, 但是无论从一些讲 Hibernate 书籍,还是他人 Blog 中都没有找到详细 介绍 Hibernate 文档中所说的原汁原味的抓取策略, 综合懒加载等等特性混在了一起, 所 以在这自己在借鉴了他人的基

Java 中的四种引用及垃圾回收策略

Java 中有四种引用:强引用.软引用.弱引用.虚引用: 其主要区别在于垃圾回收时是否进行回收: 1.强引用 使用最普遍的引用.如果一个对象具有强引用,那就 类似于必不可少的生活用品,垃圾回收器绝不会回收它.当内存空 间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题. 2.软引用(SoftReference) 如果一个对象只具有软引用,那就类似于可有可物的生活用品.如果内存空间足够,垃圾回收器就不会回收它,如果

Redis的四种工作模式实现

Redis: Redis是一款优秀的结构数据存储系统,由于出色的并发性能广为关注,可用作:数据库.缓存.消息队列:同类型的还有memcached,但是由于memcache支持的结构类型较少,并且不能够将数据持久化,慢慢的被redis所取代. Redis支持的数据结构:字符串.列表(数组).hashes(关联数组).集合.有序集合.bitmaps.hyperloglogs.空间索引:本篇博客简单介绍redis对于实现高可用和持久化的四种redis工作模式,进入正题: [TOC] 进入正题简单介绍

Java ExecutorService四种线程池使用详解

1.引言 合理利用线程池能够带来三个好处.第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗.第二:提高响应速度.当任务到达时,任务可以不需要的等到线程创建就能立即执行.第三:提高线程的可管理性.线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控.但是要做到合理的利用线程池,必须对其原理了如指掌. 2.线程池使用 Executors提供的四种线程 1.newCachedThreadPool创建一个可缓存线程池

JVM的四种GC算法

程序在运行过程中,会产生大量的内存垃圾(一些没有引用指向的内存对象都属于内存垃圾,因为这些对象已经无法访问,程序用不了它们了,对程序而言它们已经死亡),为了确保程序运行时的性能,java虚拟机在程序运行的过程中不断地进行自动的垃圾回收(GC).关于 JVM 的 GC 算法主要有下面四种: 1.引用计数算法(Reference counting) 每个对象在创建的时候,就给这个对象绑定一个计数器.每当有一个引用指向该对象时,计数器加一:每当有一个指向它的引用被删除时,计数器减一.这样,当没有引用指

Android入门:Activity四种启动模式

Android入门:Activity四种启动模式 一.启动模式介绍 启动模式简单地说就是Activity启动时的策略,在AndroidManifest.xml中的标签的android:launchMode属性设置: 启动模式有4种,分别为standard.singleTop.singleTask.singleInstance: 讲解启动模式之前,有必要先讲解一下“任务栈”的概念; 任务栈 每个应用都有一个任务栈,是用来存放Activity的,功能类似于函数调用的栈,先后顺序代表了Activity

Java四种线程池的使用

Java通过Executors提供四种线程池,分别为:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程.newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待.newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行.newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有

VirtualBox虚拟机网络设置(四种方式)

转载自:https://www.douban.com/group/topic/15558388/ VirtualBox的提供了四种网络接入模式,它们分别是: 1.NAT 网络地址转换模式(NAT,Network Address Translation) 2.Bridged Adapter 桥接模式 3.Internal 内部网络模式 4.Host-only Adapter 主机模式 第一种 NAT模式 解释: NAT模式是最简单的实现虚拟机上网的方式,你可以这样理解:Vhost访问网络的所有数据