Erlang模块supervisor翻译

概要

  通用监督者行为

描述

  一个实现监督者的行为模块,一个监督被称为子进程的其它进程的进程。一个子进程可以是另一个监督者或工作者进程。工作者进程通常的实现使用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。

  

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

时间: 2024-10-13 01:54:45

Erlang模块supervisor翻译的相关文章

理解Erlang/OTP Supervisor

http://www.cnblogs.com/me-sa/archive/2012/01/10/erlang0030.html Supervisors are used to build an hierarchical process structure called a supervision tree, a nice way to structure a fault tolerant application.                                         

ns3 Tutorial 中的日志模块(翻译)

转载地址:http://blog.sina.com.cn/s/blog_8ecca79b0101d7fe.html 1  日志模块的使用 在运行 first.cc 脚本时,我们已经简单了解了日志模块.现在,我们将更深入地了解日志子系统是为哪些用户案例设计的. 1.1 日志概述 很多大型系统支持某种消息记录功能,ns3 也不例外.在某些情况下,只有错误消息会被记录到操作控制台(在基于 Unix 的系统中通常是标准错误输出).在其他系统中,警告消息可能跟详细的信息消息一起被输出.在某些情况下,日志功

opencv文档之core模块doc翻译

core - a compact module defining basic data structures, including the dense multi-dimensional array Mat and basic functions used by all other modules. core模块:基本数据类型的定义,包括多维数组Mat和在其他所有模块中用到的基本函数 imgproc - an image processing module that includes linea

erl模块翻译

命令: erl 概述: Erlang模拟器 描述: erl程序启动一个Erlang运行时系统.准确的信息是依赖于系统的(举例,erl是否是脚本或程序,其它程序调用). 相反,windows用户可能想要使用werl程序,它运行在自己带有滚动条和支持命令行编辑的窗口.Windows上的erl程序在shell没有提供行编辑,在Windows 95无法滚回已经滚出屏幕的文本.然而,在管道或如果你想要重定向到标准输入/输出,就必须使用erl程序. 在ERTS版本5.9(OTP-R15B),运行时系统默认将

SpaceVim 语言模块 erlang

原文连接: https://spacevim.org/cn/layers/lang/erlang/ 模块简介 功能特性 启用模块 快捷键 语言专属快捷键 交互式编程 模块简介 这一模块为 SpaceVim 提供了 erlang 开发支持,包括代码补全.语法检查.以及代码格式化等特性. 功能特性 代码补全 文档查询 跳转定义处 同时,SpaceVim 还为 erlang 开发提供了交互式编程和语言服务器等功能.若要启用语言服务器,需要载入 lsp 模块. 启用模块 可通过在配置文件内加入如下配置来

erlang虚拟机代码执行原理

erlang是开源的,很多人都研究过源代码.但是,从erlang代码到c代码,这是个不小的跨度,而且代码也比较复杂.所以这里,我利用一些时间,整理下erlang代码的执行过程,从erlang代码编译过程,到代码执行过程做讲解,然后重点讲下虚拟机执行代码的原理.将本篇文章,献给所有喜欢erlang的人. erlang代码编译过程 erlang对开发者是友好的,从erlang程序文件编译成能被erlang虚拟机识别的beam文件,在这个编译过程还对开发者暴露中间代码.借助这个中间代码,我们就可以逐步

用 rebar 来构建、编译、测试、发布 Erlang 应用程序

转自:http://dhq.me/build-compile-eunit-release-erlang-application-with-rebar rebar 是一个遵循 Erlang/OTP 原则的 Erlang 项目构建工具,使用它可以减少构建标准 Erlang/OTP 项目架构配置的工作量,并且可以很容易的编译.测试.发布 Erlang 应用程序.更强大的是,rebar 提供一种依赖管理机制,它可以使开发者很方便地通过 Git.Hg 等方式重用常见的第三方 Erlang 模块或库. 安装

Erlang基础 -- 介绍 -- Erlang特点

前言 Erlang是具有多重范型的编程语言,具有很多特点,主要的特点有以下几个: 函数式 并发性 分布式 健壮性 软实时 热更新 递增式代码加载 动态类型 解释型 函数式 Erlang是函数式编程语言,函数式是一种编程模型,将计算机中的运算看做是数学中的函数计算,可以避免状态以及变量的概念. 对象是面向对象的第一型,函数式编程语言也是一样,函数是函数式编程的第一型.函数是Erlang编程语言的基本单位,在Erlang里,函数是第一型,函数几乎会被用作一切,包括最简单的计算.所有的概念都是由函数表

erlang与c之间的连接

http://blog.chinaunix.net/uid-22566367-id-382012.html erlang与c之间的连接参考资料:网络资料作者:Sunny    在Programming Erlang书上的第十二章中实现了elang与c语言之间的连接,本人觉得那个例子还是有点复杂,在此,本人举一个更简单的例子.而且在那本书上的Page 161第7行,有一个错误.书上写的是:    Port ! {PidC, {connect, Pid1}}    把端口连接进程PID从Pid1改为