Erlang Supervisor #

一、Supervisor概述 #

supervisor是Erlang/OTP中用于监控和重启子进程的行为,是构建容错系统的核心。

1.1 特点 #

  • 监控子进程
  • 自动重启
  • 监督树结构
  • 容错机制

二、基本结构 #

2.1 完整示例 #

erlang
-module(my_supervisor).
-behaviour(supervisor).
-export([start_link/0, init/1]).

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init([]) ->
    Children = [
        #{id => my_server,
          start => {my_server, start_link, []},
          restart => permanent,
          shutdown => 5000,
          type => worker,
          modules => [my_server]}
    ],
    {ok, {#{strategy => one_for_one, intensity => 1, period => 5}, Children}}.

三、监督策略 #

3.1 one_for_one #

erlang
init([]) ->
    {ok, {#{strategy => one_for_one, intensity => 1, period => 5}, []}}.

只重启崩溃的子进程。

3.2 one_for_all #

erlang
init([]) ->
    {ok, {#{strategy => one_for_all, intensity => 1, period => 5}, []}}.

重启所有子进程。

3.3 rest_for_one #

erlang
init([]) ->
    {ok, {#{strategy => rest_for_one, intensity => 1, period => 5}, []}}.

重启崩溃进程及其后的所有进程。

3.4 simple_one_for_one #

erlang
-module(dynamic_supervisor).
-behaviour(supervisor).
-export([start_link/0, start_child/1, init/1]).

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

start_child(Args) ->
    supervisor:start_child(?MODULE, [Args]).

init([]) ->
    ChildSpec = #{id => worker,
                  start => {my_worker, start_link, []},
                  restart => temporary,
                  shutdown => 5000,
                  type => worker,
                  modules => [my_worker]},
    {ok, {#{strategy => simple_one_for_one, intensity => 10, period => 60}, [ChildSpec]}}.

四、子进程规格 #

4.1 规格字段 #

erlang
#{id => ChildId,
  start => {Module, Function, Args},
  restart => Restart,
  shutdown => Shutdown,
  type => Type,
  modules => Modules}

4.2 restart选项 #

选项 说明
permanent 总是重启
transient 异常退出时重启
temporary 从不重启

4.3 shutdown选项 #

选项 说明
brutal_kill 强制杀死
infinity 无限等待
整数 等待毫秒数

4.4 type选项 #

选项 说明
worker 工作进程
supervisor 监督者

五、强度限制 #

5.1 intensity和period #

erlang
{ok, {#{strategy => one_for_one, intensity => 5, period => 60}, Children}}

在period秒内最多重启intensity次。

5.2 超过限制 #

超过限制时,监督者自身退出。

六、监督树 #

6.1 多层监督 #

erlang
-module(top_supervisor).
-behaviour(supervisor).
-export([start_link/0, init/1]).

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init([]) ->
    Children = [
        #{id => server_sup,
          start => {server_supervisor, start_link, []},
          type => supervisor},
        #{id => worker_sup,
          start => {worker_supervisor, start_link, []},
          type => supervisor}
    ],
    {ok, {#{strategy => one_for_one, intensity => 1, period => 5}, Children}}.

6.2 主监督者 #

erlang
-module(main_supervisor).
-behaviour(supervisor).
-export([start_link/0, init/1]).

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init([]) ->
    Children = [
        #{id => cache_server,
          start => {cache_server, start_link, []},
          restart => permanent},
        #{id => db_connection_pool,
          start => {pool_supervisor, start_link, []},
          type => supervisor}
    ],
    {ok, {#{strategy => rest_for_one, intensity => 5, period => 60}, Children}}.

七、动态子进程 #

7.1 添加子进程 #

erlang
start_child(Supervisor, ChildSpec) ->
    supervisor:start_child(Supervisor, ChildSpec).

7.2 终止子进程 #

erlang
terminate_child(Supervisor, ChildId) ->
    supervisor:terminate_child(Supervisor, ChildId).

7.3 删除子进程 #

erlang
delete_child(Supervisor, ChildId) ->
    supervisor:delete_child(Supervisor, ChildId).

八、实际应用 #

8.1 应用监督者 #

erlang
-module(app_supervisor).
-behaviour(supervisor).
-export([start_link/0, init/1]).

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init([]) ->
    Children = [
        #{id => config_server,
          start => {config_server, start_link, []},
          restart => permanent,
          shutdown => 5000},
        #{id => db_pool,
          start => {db_pool_supervisor, start_link, []},
          type => supervisor},
        #{id => api_server,
          start => {api_server, start_link, []},
          restart => permanent,
          shutdown => 10000},
        #{id => background_worker_sup,
          start => {worker_supervisor, start_link, []},
          type => supervisor}
    ],
    {ok, {#{strategy => rest_for_one, intensity => 5, period => 60}, Children}}.

8.2 连接池监督者 #

erlang
-module(pool_supervisor).
-behaviour(supervisor).
-export([start_link/1, init/1]).

start_link(Size) ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, [Size]).

init([Size]) ->
    Children = [
        #{id => {connection, I},
          start => {connection_worker, start_link, []},
          restart => permanent,
          shutdown => 5000}
     || I <- lists:seq(1, Size)],
    {ok, {#{strategy => one_for_one, intensity => Size, period => 60}, Children}}.

九、总结 #

本章学习了:

  • Supervisor概述
  • 基本结构
  • 监督策略
  • 子进程规格
  • 强度限制
  • 监督树
  • 动态子进程
  • 实际应用

准备好学习Application了吗?让我们进入下一章。

最后更新:2026-03-27