1. 监督规则

一个监督者负责启动、停止、监控他的子进程。监督者的一个基本概念就是当必要的时候重启子进程保证它们的存活

哪个子进程要重启和被监控是由一个子规程列表决定的,子进程按照列表中指定的顺序启动,并按相反的顺序终止

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定义了最大重启频率
{ch3, …}是子规程

3. 重启策略

one_for_one

假如一个进程终止了,仅仅这个进程会被重启

one_for_all

假如一个进程停止了,所有其他子进程也要被停止,然后所有子进程,包括这个引发停止的子进程都被重启

rest_for_one

假如一个进程停止了,它后面的子进程,也就是以启动顺序来说这个被终止的进程后面的子进程都将被停止,然后他们又被启动。

4. 最大启动频率

监督者有一个内建机制限制在给定的时间间隔里的重启次数,这由子进程启动规程中的两个参数值决定,MaxR和MaxT,它们定义在回调函数init中

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

如果在时间MaxT里重启次数大于MaxR ,监督者进程就停止它所有子进程,然后再终止自己。

当监督者进程终止了,那么更高级别的监督者要采取些动作,它或者重启被终止的监督者或者停止自己

这个重启机制的目的是预防一个进程因某种原因频繁的终止,然后简单的重启。

5. 子规范

下面的是类型定义

{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用来内部标识子规范

  • StartFunc是启动子进程时调用的函数,它将成为对supervisor:start_link, gen_server:start_link, gen_fsm:start_link or gen_event:start_link的调用

  • Restart标识一个进程终止后将怎样重启,一个permanent 进程总会被重启;一个temporary 进程从不会被重启;一个transient 进程仅仅当是不正常的被终止后才重启,例如非normal得退出原因

  • Shutdown 定义一个进程将怎样被终止,brutal_kill意味着子进程被exit(Child, kill)无条件的终止;一个整数值的超时时间意味着监督者告诉子进程通过调用exit(Child, shutdown)而被终止,然后等待一个返回的退出信号,假如在指定的时间里没有收到退出信号,那么子进程用exit(Child, kill)被无条件终止。

  • Type指定子进程是supervisor还是worker

  • Modules 是有一个元素的列表[Module],假如子进程是supervisor、gen_server 或 gen_fsm,那么Module 是回调模块的名称;假如子进程是gen_event,那么Modules 应该是dynamic

例如:子规范用于启动一个服务器ch3

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

子规范用于启动一个事件管理器

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

监督者然后根据子规程启动所有子进程,这个例子中是一个子进程ch3

6. 启动supervisor

像这样

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

启动

监督者进程调用init

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

并期待init返回{ok, StartSpec}

注意supervisor:start_link是同步的,它一直等到所有子进程都启动了才返回

7. 添加子进程

除静态监控树外,我们也可以通过supervisor:start_child(Sup, ChildSpec)向监督者动态添加子进程,Sup 是监督者的pid或名称,ChildSpec 是一个子规范。子进程用start_child/2来添加。注意:假如监督者死掉后重启,那么所有动态添加的子进程都不复存在

8. 停止子进程

任何静态动态添加的子进程都可以用supervisor:terminate_child(Sup, Id)来停止。一个停止子进程规范可以用supervisor:delete_child(Sup, Id)来删除。Sup是监督者的pid或名称,Id是子规范的id

9. Simple-One-For-One

监督者的simple_one_for_one启动策略是one_for_one的简版,所有子进程都是同一进程实例而被动态添加,下面是一个simple_one_for_one监督者的实例

-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:start_child(Sup, List)来动态添加,Sup 是监督者的pid或名称,List 是添加给子规范中指定参数列表term列表,如果启动函数是{M, F, A}这种形式,那么子进程通过调用apply(M, F, A++List)而被启动

例如,给上面的例子添加一个子进程

supervisor:start_child(Pid, [id1])

那么子进程通过调用apply(call, start_link, []++[id1])而被启动,实际上就是call:start_link(id1)

10. 停止

因为监控者是监控树的一部分,它自动被他的监督者停止,根据相应规范,它反序停止它的所有子进程,然后终止自己

至此,四种behavour已经全部翻译完了,熟练应用他们是你构建高扩展、高容错、高并发应用的基础,努力吧!

本文属转载

原作者:老纪

原载:老纪博客版权所有。转载时必须以链接形式注明转载自老纪博客 [http://www.jifuyi.com/]。

转载于:https://blog.51cto.com/powerfly1009/1561734

erlang四大behaviour之四-supervisor(转载)相关推荐

  1. erlang四大behaviour简述

    应用erlang的behaviour 框架(gen_server,gen_fsm,gen_event,supervisor)在处理很多情况的时候省下大量不必要的代码,使用的时候在框架基础添加自定义逻辑 ...

  2. erlang OTP中的四大behaviour fsm的例子

    下面是一个fsm的例子,代码如下: 1 -module(code_lock2). 2 3 -behaviour(gen_fsm). 4 -export([start_link/1]). 5 -expo ...

  3. android四大组件之四-BroadCast实现原理分析

    前言: 一开始的目标是解决各种各样的ANR问题的,但是我们知道,ANR总体上分有四种类型,这四种ANR类型有三种是和四大组件相对应的,所以,如果想了解ANR发生的根因,对安卓四大组件的实现原理必须要懂 ...

  4. Erlang OTP学习(3) supervisor

    今天细致的看了下supervisor,现在做个总结:    其中,方块代表supervisor process,它的功能很简单,就负责看管它下面的"小弟"(child proces ...

  5. Erlang/OTP设计原则(文档翻译)

    http://erlang.org/doc/design_principles/des_princ.html 图和代码皆源自以上链接中Erlang官方文档,翻译时的版本为20.1. 这个设计原则,其实 ...

  6. ARM Mali GPU 四大微架构概述

    Background 对于手机终端来说,GPU图像处理能力是衡量一台手机的性能标杆.首先,是UI流畅性,大家拿到手机都得先划来划去看下UI是否流畅,而UI其实主要还是用GPU渲染的:其次是游戏的流畅性 ...

  7. Direct3D中的四大变换

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhmxy555/article/details/8408723 作者:毛星云(浅墨 ...

  8. 【Visual C++】游戏开发笔记三十八 浅墨DirectX提高班之六 携手迈向三维世界 四大变换展身手

    分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow 本系列文章由zhm ...

  9. 在OSX上安装Erlang

    2019独角兽企业重金招聘Python工程师标准>>> 发现一个在OSX上安装Erlang的简单方法,和大家分享一下. 首先需要安装 Homebrew .打开终端,输入如下命令并回车 ...

最新文章

  1. 2022-2028年中国氟硅橡胶产业发展动态及投资前景分析报告
  2. 在C语言里_大学生:我学了这么久的C语言,为什么感觉它啥都做不了?网友:恰恰相反!...
  3. 关于移除节点的IE和Firefox的兼容问题
  4. IIS怎么设置本地域名解析(本地域名测试配置)
  5. Geany 权限问题:Error opening file ... : permission denied.,原因及解决办法。
  6. linux shell 脚本攻略学习11--mkdir和touch命令详解
  7. java支付管理有源码_java支付宝支付案例源码
  8. 输出三角形字符阵列 (15 分)
  9. 【AudioVideo】处理音频输出的变化(13)
  10. ARM处理器与架构对应关系
  11. windows下 dos 执行php 代码
  12. 数据结构课程设计之简单计算器的实现
  13. centos下使用pngquant批量压缩png图片
  14. feign Ambiguous mapping 解决方式
  15. 常见硬件通信协议介绍
  16. 家庭用药助手:丁香园推出面向大众家庭用户的药品信息服务工具
  17. 国标、行标、地标、团标、企标以及国际标准的基础知识
  18. 美国新奥尔良 zip_在新奥尔良启动公开和交互式预算数据
  19. 语言模型训练工具SRILM
  20. IP 地址与整数之间的互相转换详解

热门文章

  1. 【前端】CKeditor屏蔽“浏览服务器”功能
  2. 在 Linux 下搭建 Git 服务器
  3. 用JS中的cookie实现商品的浏览记录
  4. Owin的URL编码怎么搞?以前都是HttpUtility.UrlEncode之类的,现在连system.web都没了,肿么办?...
  5. Mean Shift具体介绍
  6. Ubuntu设置目录的读写权限(Linux命令chmod 777 dirName)
  7. 安装keepalived执行make报错的解决方法
  8. OO视角的重构技巧-if\switch 的消除
  9. Linux 命令(81)—— chmod 命令
  10. kafka消息队列学习笔记