概要
  通用监督者行为
 
描述
  一个实现监督者的行为模块,一个监督被称为子进程的其它进程的进程。一个子进程可以是另一个监督者或工作者进程。工作者进程通常的实现使用gen_event,gen_fsm和gen_server中的行为。监督者使用这个模块实现一组标准的接口函数和包括跟踪和错误报告的功能。监督者被用来构建称为监控树的分层进程结构,一个构建容错应用的很好的方式。参考OTP设计原理获得更多信息。
 
  监督者设定哪些子进程被监督的定义,位于导出一组预定义函数的回调模块。
 
  除非另作说明,如果指定的supervisor不存在或给出错误参数,该模块所有函数会失败。
 
  监督原则:
  监督者负责启动、停止和监控它的子进程。监督者的基本思想是,它应该保证它的子进程活着,必要时重启它们。
 
  监督者的子进程被定义为子规范列表。当监督者被启动时,子进程依据这个列表从左到右按顺序被启动。当监督者终止时,它首先按相反的启动顺序,从右到左终止它的子进程。
 
  监督者可以有以下重启策略之一:
  one_for_one - 如果子进程终止,应重新启动,只有子进程受到影响。
  one_for_all - 如果子进程终止,应重新启动,所有其它子进程终止,那么所有的子进程被启动。
  rest_for_one - 如果子进程终止,应重新启动,后面的子进程,也就是说,按启动顺序,被终止进程的后面的子进程被终止。那么,终止进程和它后面所有的子进程被重启。
  simple_one_for_one - 简化的one_for_one监督者,其中,所有的子进程被动态添加同样进程类型的实例,也就是,运行相同的代码。
 
  对于simple_one_for_one监督者,函数delete_child/2 和 restart_child/2是有效的。如果指定的监督者使用该重启策略,会返回{error,simple_one_for_one}。
 
  在simple_one_for_one监督者下,通过给定子进程的进程号作为第二个参数,函数terminate_child/2可被用于子进程。如果子规范标识符被使用,terminate_child/2将返回{error,simple_one_for_one}。
 
  因为一个simple_one_for_one监督者可以有很多的子进程,它在同一时间将它们关闭。所以,它们被停止的顺序没有被定义。出于同样的原因,它可能有一个开销对于关闭策略。
 
  为防止监督者进入子进程终止和重启的无限循环,使用两个整数MaxR 和 MaxT定义最大重启频率。如果在MaxT秒重启超过MaxR发生,监督者终止所有子进程,随后终止它自己。
 
  这是子规范的类型定义:
child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
  Id = term()
  StartFunc = {M,F,A}
    M = F = atom()
  A = [term()]
 Restart = permanent | transient | temporary
 Shutdown = brutal_kill | int()>0 | infinity
 Type = worker | supervisor
 Modules = [Module] | dynamic
    Module = atom()
   Id是一个名称,在内部被监督者用于标识子规范。
  
   StartFunc定义函数调用用于启动子进程。它应该是一个模块-函数-参数元组{M,F,A}用作apply(M,F,A)。
   启动函数必须创建和链接到子进程,应该返回{ok,Child}或{ok,Child,Info},其中Child是子进程的进程号,Info是任意term被监督者忽略。
 
   如果子进程因为一些原因不能启动,启动函数也可以返回ignore,这种情况,子规范将会被监督者保存(除非它是temporary进程),但不存在的子进程将被忽略。
 
   如果出现错误,函数也可能返回错误元组{error,Error}。
 
   请注意,start_link函数,不同的行为模块满足上述的要求。
 
   Restart定义什么时候终止的子进程应该被重启。一个permanent子进程应该总是被重启,一个temporary子进程从不被重启(即使当监督者的重启策略是rest_for_one或one_for_all和兄弟进程的挂掉导致temporary进程被终止),和一个transient子进程应该被重启仅当它异常终止,也就是说,除过normal,shutdown或{shutdown,Term}的其它退出原因。
 
   Shutdown定义子进程应该如何被终止。brutal_kill意味着子进程将被无条件终止使用exit(Child,kill)。一个整数超时值意味着监督者将告诉子进程通过调用exit(Child,shutdown)来终止,然后以原因shutdown等待来自子进程的退出信号。如果在指定数目毫秒内没有收到退出信号,子进程使用exit(Child,kill)被无条件终止。
 
   如果子进程是另一个监督者,Shutdown应该被设置成infinity,给子树充足的时间关闭。如果子进程是工作者,它也被允许设置成infinity。
 
   警告:小心设置shutdown策略为infinity,当子进程是一个工作者。因为,在这种情形下,监控树的终止取决于子进程,它必须以安全的方式实现,它的清理过程必须返回。
 
   请注意,所有子进程自动使用标准OTP行为模块实现依据关闭协议。
 
   Type指定子进程是监督者还是工作者。
 
   Modules被版本处理程序使用,在代码替换期间用于确定哪些进程使用哪些模块。作为一个经验法则,Modules应该一个元素列表[Module],其中,Module是回调模块,如果子进程是一个supervisor, gen_server 或 gen_fsm。如果子进程是一个带有回调模块集合的事件管理器(gen_event),Modules应该是dynamic。关于版本控制的更多信息参考OTP设计原则。
 
   内部地,监督者也跟踪子进程的进程号,或undefined如果没有进程号存在。
 
数据类型
child() = undefined | pid()
child_id() = term() %% 不是pid()
child_spec() =
{Id :: child_id(),
StartFunc :: mfargs(),
Restart :: restart(),
Shutdown :: shutdown(),
Type :: worker(),
Modules :: modules()}
mfargs() = {M :: module(), F :: atom(), A :: [term()] | undefined} %% 如果Restart是temporary,A的值为undefined。
modules() = [module()] | dynamic
restart() = permanent | transient | temporary
shutdown() = brutal_kill | timeout()
strategy() = one_for_all | one_for_one | rest_for_one | simple_one_for_one
sup_ref() = (Name :: atom())
| {Name :: atom(), Node :: node()}
| {global, Name :: atom()}
| {via, Module :: module(), Name :: any()}
| pid()
worker() = worker | supervisor
 
导出
start_link(Module, Args) -> startlink_ret()
start_link(SupName, Module, Args) -> startlink_ret()
Types:
  SupName = sup_name()
  Module = module()
  Args = term()
  startlink_ret() = {ok, pid()} | ignore | {error, startlink_err()}
  startlink_err() = {already_started, pid()} | {shutdown, term()} | term()
    sup_name() = {local, Name :: atom()} | {global, Name :: atom()} | {via, Module :: module(), Name :: any()}

  创建一个监督者进程作为监控树的一部分,在其它方面,函数将确保监督者链接到调用者进程(它的监督者)。

 
  被创建的监督者进程调用Module:init/1找出重启策略、最大启动频率和子进程。为确保同步启动过程,start_link/2,3不会返回直到Module:init/1已经返回且所有子进程已被启动。
 
  如果SupName={local,Name},supervisor使用register/2被注册为本地的Name。如果SupName={global,Name},supervisor使用global:register_name/2被注册为全局的Name。如果没有提供Name,supervisor不会被注册。如果SupName={via,Module,ViaName},supervisor将会用Module代表的注册表注册。Module回调应该导出函数register_name/2, unregister_name/1, whereis_name/1 和 send/2,它们表现得像global模块对应的函数。因此,{via,global,Name}是一个有效地引用。
 
  如果没有提供名称,监督者不会注册。
 
  Module是回调模块的名称。
 
  Args是一个任意term,作为参数传递给Module:init/1。
 
  如果监督者和它的子进程被成功创建,(也就是说,如果所有子进程启动函数返回{ok,Child}, {ok,Child,Info}, 或 ignore)函数返回{ok,Pid},其中Pid是监督者的进程号。如果已存在指定SupName的进程,函数返回{error,{already_started,Pid}},其中,Pid是那个进程的进程号。
 
  如果Module:init/1返回ignore,该函数也返回ignore,而监督者以原因normal终止。如果Module:init/1失败或返回不正确的值,该函数返回{error,Term},其中,Term是包含关于错误信息的Term,监督者以原因Term终止。
 
  如果任何子进程启动函数是失败或返回一个错误元组或一个错误值,监督者首先将以原因shutdown终止所有已启动的进程,随后终止它自己,然后返回{error, {shutdown, Reason}}。
 
start_child(SupRef, ChildSpec) -> startchild_ret()
Types:
  SupRef = sup_ref()
  ChildSpec = child_spec() | (List :: [term()])
  child_spec() =
  {Id :: child_id(),
  StartFunc :: mfargs(),
  Restart :: restart(),
  Shutdown :: shutdown(),
  Type :: worker(),
  Modules :: modules()}
  startchild_ret() = {ok, Child :: child()} | {ok, Child :: child(), Info :: term()} | {error, startchild_err()}
  startchild_err() = already_present | {already_started, Child :: child()} | term()

  动态增加一个子规范到监督者SuperRef,它启动对应的子进程。

  ServerRef可以是:
  • 进程号;
  • Name,supervisor被本地注册的名称;
  • {Name,Node},supervisor在其它节点被本地注册;
  • {global,Name},supervisor被全局注册;
  • {via,Module,ViaName},supervisor通过替代的进程注册表注册。
 
  ChildSpec应该是有效的子进程(除非该监督者是一个simple_one_for_one的监督者,看下面)。子进程将会使用定义在子规范的启动函数启动。
 
  如果是simple_one_for_one监督者的情况下,定义在Module:init/1的子规范将被使用,ChildSpec应该是一个任意term列表。子进程将被启动通过添加List到已存在的启动函数参数,也就是说,通过调用apply(M, F, A++List),其中,{M,F,A}是定义在子规范的启动函数。
 
  如果已经存在一个指定id的子规范,ChildSpec被丢弃,函数返回{error,already_present} 或 {error,{already_started,Child}},取决于对应的子进程是否运行。
 
  如果子进程启动函数返回{ok,Child} 或 {ok,Child,Info},子规范和进程号被添加到监督者,函数返回相同的值。
  如果子进程启动函数返回ignore,子规范被添加到监督者,进程号设置为undefined,函数返回{ok,undefined}。
  如果子进程启动哈数返回一个错误元组或一个错误值, 或它失败,子规范被丢弃,函数返回{error,Error},其中Error是一个包含关于错误和子规范信息的term。
 
terminate_child(SupRef, Id) -> Result
Types:
  SupRef = sup_ref()
  Id = pid() | child_id()
  Result = ok | {error, Error}
    Error = not_found | simple_one_for_one
  告诉监督者SupRef终止给定的子进程。
 
  如果监督者不是simple_one_for_one,Id必须是子规范标识符。进程被终止,如果有,除非它是temporary子进程,子规范被监督者保存。子进程随后可能被监督者重启。子进程也可能显式的通过调用restart_child/2被重启。使用delete_child/2移除子规范。
 
  如果子进程是temporary,进程一终止,子规范就被删除。这意味着delete_child/2没有意义,restart_child/2无法用于这些进程。
 
  如果监督者是simple_one_for_one,Id必须是子进程的pid(),如果指定的进程活着,但不是给定监督者的子进程,函数将返回{error,not_found}。如果给定子规范标识,而不是pid(),函数将返回{error,simple_one_for_one}。
 
  如果成功,函数返回ok。如果没有指定Id的子规范,函数返回{error,not_found}。
 
  参考start_child/2了解SupRef的描述。
 
restart_child(SupRef, Id) -> Result
Types:
  SupRef = sup_ref()
  Id = child_id()
  Result = {ok, Child :: child()} | {ok, Child :: child(), Info :: term()} | {error, Error}
    Error = running | restarting | not_found | simple_one_for_one | term()

  告诉监督者SupRef重启一个子进程根据子规范标识符Id。子规范必须存在,对应子进程必须没有在运行。

 
  请注意temporary子进程,当子进程终止,子规范自动被删除。随后,它不能重启这些子进程。
 
  参看start_child/2了解SupRef的描述。
 
  如果子规范标识Id不存在,函数返回{error,not_found}。如果子规范存在但对应进程已经运行,函数返回{error,running}。
 
  子进程启动函数返回{ok,Child} 或 {ok,Child,Info},进程号被添加到监督者,函数返回相同的值。
  子进程启动函数返回ignore,进程号仍然设置为undefined,函数返回{ok,undefined}。
  子进程启动函数返回一个错误元组或一个错误值,或它失败,函数返回{error,Error},其中,Error是一个包含错误信息的term。
 
which_children(SupRef) -> [{Id, Child, Type, Modules}]
Types:
  SupRef = sup_ref()
  Id = child_id() | undefined
  Child = child() | restarting
  Type = worker()
  Modules = modules()

  返回一个新创建列表,含有所有子规范和归属于监督者SupRef的子进程。

 
  请注意,在低内存状态下,监督大量子进程,调用该函数可能导致内存不足的异常。
 
  参考start_child/2了解SupRef的描述。
 
  对于每个子规范/进程给出的信息是:
  • Id - 子规范中定义或在simple_one_for_one监督者情况下为undefined;
  • Child - 对应子进程的进程号,函数将被重启为restarting或没有该进程为undefined;
  • Type - 定义在子规范;
  • Modules - 定义在子规范。

count_children(SupRef) -> PropListOfCounts
Types:
  SupRef = sup_ref()
  PropListOfCounts = [Count]
  Count = {specs, ChildSpecCount :: integer() >= 0} | {active, ActiveProcessCount :: integer() >= 0}
| {supervisors, ChildSupervisorCount :: integer() >= 0} | {workers, ChildWorkerCount :: integer() >= 0}
  返回一个属性列表,它包含监督者子规范的下列元素和被管理的进程的数量:
  • specs - 子进程活的或死的总数量;
  • active - 所有被监督者管理的激活的运行的子进程数量;
  • supervisors - 在规范列表被标记为child_type = supervisor的所有子进程数量,不管子进程是否活着;
  • workers - 在规范列表被标记为child_type = worker的所有子进程数量,不管子进程是否活着;
 
check_childspecs(ChildSpecs) -> Result
Types:
  ChildSpecs = [child_spec()]
  Result = ok | {error, Error :: term()}

  该函数需要一个子规范列表作为参数,如果他们在语法上都正确,返回ok,否则返回{error,Error}。

 
回调函数
Module:init(Args) -> Result
Types:
  Args = term()
  Result = {ok,{{RestartStrategy,MaxR,MaxT},[ChildSpec]}} | ignore
  RestartStrategy = strategy()
  MaxR = integer()>=0
  MaxT = integer()>0
  ChildSpec = child_spec()

  无论何时使用supervisor:start_link/2,3 监督者被启动,函数被一个新的进程调用找出重启策略、最大重启频率和子规范。

 
  Args是提供给启动函数的参数。
 
  RestartStrategy是重启策略,MaxR 和 MaxT定义监督者的最大重启频率。 [ChildSpec]是一组有效地子规范,它定义哪些进程监督者应该启动和监控。参看上面关于监督原则的讨论。
 
  请注意,当重启策略为simple_one_for_one,子规范列表必须只含有一个子规范列表(ID被忽略)。在初始化期间,没有子进程随后被启动,但是所有子进程被设定使用supervisor:start_child/2来动态启动。
 
  函数也可能返回ignore。
 
  

  翻译有问题的地方,请大家指正。

Erlang模块supervisor翻译的更多相关文章

  1. Erlang模块erl翻译

    命令:     erl 概述:     Erlang模拟器 描述:     erl程序启动一个Erlang运行时系统.准确的信息是依赖于系统的(举例,erl是否是脚本或程序,其它程序调用).     ...

  2. Erlang模块gen_server翻译

    gen_server 概要: 通用服务器行为描述: 行为模块实现服务器的客户端-服务器关系.一个通用的服务器进程使用这个模块将实现一组标准的接口功能,包括跟踪和错误报告功能.它也符合OTP进程监控树. ...

  3. Erlang模块file翻译

    模块摘要     文件接口模块   描述     模块file提供了文件系统的接口.     在具有线程支持的操作系统上,可以让文件操作以其自己的线程执行,从而允许其他Erlang进程与文件操作并行地 ...

  4. Erlang模块ets翻译

    概要: 内置的存储 描述: 这个模块是Erlang内置存储BIFs的接口.这些提供了在Erlang运行时系统中存储大量数据的能力,并且能够对数据进行持续的访问时间.(在ordered_set的情况下, ...

  5. Erlang模块gen_fsm翻译

    模块摘要     通用有限状态机行为.   描述     用于实现有限状态机的行为模块.使用该模块实现的通用有限状态机进程(gen_fsm)将具有一组标准的接口函数,并包括用于跟踪和错误报告的功能.它 ...

  6. Erlang模块gen_tcp翻译

    概述 TCP/IP套接字接口 描述 gen_tcp模块提供了使用TCP / IP协议与套接字进行通信的功能. 以下代码片段提供了一个客户端连接到端口5678的服务器的简单示例,传输一个二进制文件并关闭 ...

  7. Erlang模块inet翻译

    模块 inet 模块概述 访问TCP / IP协议. 描述 此模块提供对TCP/IP协议的访问. 另请参阅<ERTS用户指南:Inet配置>,以获取有关如何配置用于IP通信的Erlang运 ...

  8. 理解Erlang/OTP Supervisor

    http://www.cnblogs.com/me-sa/archive/2012/01/10/erlang0030.html Supervisors are used to build an hie ...

  9. [Erlang25]Erlang in anger 翻译

    Erlang in anger     Erlang in anger 是写Learn some Erlang的帅小伙(照片真是帅死啦)写的,一共87页,可以随意下载(英文原版):http://www ...

随机推荐

  1. Apache NiFi 核心概念和关键特性

    本文来源于官方文档翻译 NiFi 的核心概念 NiFi 最早是美国国家安全局内部使用的工具,用来投递海量的传感器数据.后来由 apache 基金会开源.天生就具备强大的基因.NiFi基本设计理念与 F ...

  2. SpringBoot-Admin的使用

    [**前情提要**]Spring Boot Actuator 提供了对单个 Spring Boot 应用的监控,信息包含应用状态.内存.线程.堆栈等,比较全面的监控了 Spring Boot 应用的整 ...

  3. 如何实现css渐变圆角边框

    最近设计师的风格发生突变,一句话概括就是,能用渐变的地方绝对不用纯色.这不,就整出了一个渐变圆角边框.这渐变好做,圆角好做,渐变圆角也没问题,可是在加个边框还是有点坑的.没办法,看看怎么实现吧 bor ...

  4. Javascript中将数字转换为中文的方法

    //js实现将数字1234转化为汉字字符串(一千二百三十四)(或大写汉字壹仟贰佰叁拾肆): /*阿拉伯数字转中文数字 中文数字的特点: 每个计数数字都跟着一个权位,权位有:十.百.千.万.亿. 以“万 ...

  5. oracle 正则表达的使用

    最近遇到有个项目,需要根据文件存储的根目录地址来判断是在云端获取,还是本地获取, 先看下具体有几个不同的根目录: , , 'i') from pmc.designmaterial d 去重关键字:di ...

  6. Django上线部署之Apache

    环境: 1.Windows Server 2016 Datacenter 64位 2.SQL Server 2016 Enterprise 64位 3.Python 3.6.0 64位 4.admin ...

  7. 如何美观地打印 Python 对象?这个标准库可以简单实现

    前不久,我写了一篇文章回顾 Python 中 print 的发展历史 ,提到了两条发展线索: 明线:早期的 print 语句带有 C 和 Shell 的影子,是个应用程序级的 statement,在最 ...

  8. spring data jpa 的使用

    使用spring data jpa 开发时,发现国内对spring boot jpa全面介绍的文章比较少案例也比较零碎,因此写文章总结一下. spring data jpa介绍 首先了解JPA是什么? ...

  9. 集合系列 List(三):Vector

    Vector 的底层实现以及结构与 ArrayList 完全相同,只是在某一些细节上会有所不同.这些细节主要有: 线程安全 扩容大小 线程安全 我们知道 ArrayList 是线程不安全的,只能在单线 ...

  10. Count the string[KMP]HDU3336

    题库链接http://acm.hdu.edu.cn/showproblem.php?pid=3336 这道题是KMP的next数组的一个简单使用,首先要理解next数组的现实意义:next[i]表示模 ...