Erlang supervision trees helps bring fault tolerance, recovery and robustness to erlang applications. The presentation goes through basic and advanced examples along with supervision strategies.
2. HELLO!
I am Akhil Agrawal
Doing Erlang development for last five years
Doing Ejabberd development for last eight months now
Started BIZense in 2008 & Digikrit in 2015
4. ERLANG SUPERVISION TREES
Supervision strategy consists of two steps – first to
form the supervision trees and then providing
restart strategy at each level to follow when child
dies, which could affect other children
Supervision Strategies
Supervisors can supervise workers and other
supervisors forming supervision tree, while workers
should never be used in any position except under
another supervisor
Supervision Trees
Complete examples of supervisors from the
opensource projects like rabbitmq, ejabberd
and others to get some understanding of how
supervisors are used in real world
Complete Examples
A supervisor is responsible for starting, stopping,
and monitoring its child processes. The basic idea
of a supervisor is that it is to keep its child
processes alive by restarting them when necessary
Basics
5. Basics – Erlang Supervision (Without Supervisor Behavior)
Linked processes - terminating process sends an exit signal to all linked processes but for supervision, supervisor
should also trap exits - process instead of exiting, receives message of the form: {'EXIT', From, Reason}
start_link() ->
SupPid = spawn(classic_sup, supervisor, [basic_worker, start_link, undefined]),
register(classic_sup, SupPid),
SupPid ! {'INIT'},
{ok, SupPid}.
receive ->
{'INIT'} -> process_flag(trap_exit, true),
{ok, NewPid} = apply(Module, Function, []),
link(NewPid),
error_logger:info_msg("Initializing the worker with pid ~p~n", [NewPid]),
supervisor(Module, Function, NewPid);
{'EXIT', Pid, Reason} -> {ok, NewPid} = apply(Module, Function, []),
link(NewPid),
error_logger:info_msg("Process basic_worker pid ~p terminated due to ~p, new pid is
~p~n", [Pid, Reason, NewPid]),
supervisor(Module, Function, NewPid);
end.
7. Advanced – Multi-level Supervision
Supervisors can form a tree by supervising other
supervisors and workers
SupFlags = {RestartStrategy, Intensity, Period},
ChildSpecs = [ %% advanced_worker
{advanced_worker_spec,
{advanced_worker, start_link, []},
permanent,
brutal_kill,
worker,
[advanced_worker]},
%% basic_sup
{basic_sup_spec,
{basic_sup, start_link, []},
permanent,
brutal_kill,
supervisor,
[basic_sup, basic_worker]}],
{ok, {SupFlags, ChildSpecs}}. Image from Erlang/OTP Supervision Presentation
8. SUPERVISION STRATEGIES
If a child process terminates, all
other child processes are
terminated, and then all child
processes, including the
terminated one, are restarted
one_for_all
It is a simplified one_for_one
supervisor, where all child
processes are dynamically added
instances of the same process
simple_one_for_one
If a child process terminates,
only that process is restarted
one_for_one
If a child process terminates, the
rest of the child processes (that
is, the child processes after the
terminated process in start order)
are terminated. Then the
terminated child process and rest
of child processes are restarted
rest_for_one Erlang
Supervision
Strategies
9. Advanced – Supervision Strategy one_for_one
If a child process terminates, only that process is
restarted.
start_link({RestartStrategy, Intensity, Period}) ->
supervisor:start_link({local, ?SERVER}, ?MODULE,
[{RestartStrategy, Intensity, Period}]).
init(Args = [{RestartStrategy, Intensity, Period}]) ->
SupFlags = {RestartStrategy, Intensity, Period},
one_for_one_test_() ->
{foreachx, fun(Args) -> strategy_setup(Args) end,
fun(Args, Pid) -> strategy_cleanup(Args, Pid) end,
[
{{one_for_one, 1, 5},
named_advanced_worker_restarted("one_for_one_advanced_worker
_restarted")},
{{one_for_one, 1, 5},
named_basic_sup_restarted("one_for_one_basic_sup_restarted")
}
]}.
10. Advanced – Supervision Strategy one_for_all
If a child process terminates, all other
child processes are terminated, and then
all child processes, including the
terminated one, are restarted
one_for_all_test_() ->
{foreachx, fun(Args) ->
strategy_setup(Args) end, fun(Args,
Pid) -> strategy_cleanup(Args, Pid)
end,
[
{{one_for_all, 1, 5},
named_advanced_worker_restarted("one_f
or_all_advanced_worker_restarted")},
{{one_for_all, 1, 5},
named_basic_sup_restarted("one_for_all
_basic_sup_restarted")}
]}. Image from Erlang/OTP Supervision Presentation
11. Advanced – Supervision Strategy rest_for_one
If a child process terminates, the rest of the
child processes (that is, the child processes
after the terminated process in start order) are
terminated. Then the terminated child process
and rest of child processes are restarted
rest_for_one_test_() ->
{foreachx, fun(Args) ->
strategy_setup(Args) end, fun(Args, Pid) ->
strategy_cleanup(Args, Pid) end,
[
{{rest_for_one, 1, 5},
named_advanced_worker_restarted("rest_for_o
ne_advanced_worker_restarted")},
{{rest_for_one, 1, 5},
named_basic_sup_restarted("rest_for_one_bas
ic_sup_restarted")}
]}.
http://learnyousomeerlang.com/supervisors
http://ferd.ca/the-zen-of-erlang.html
14. THANKS!
Any questions?
You can find me at
@digikrit / akhil@digikrit.com
Special thanks to all the people who made and released these awesome resources for free:
Presentation template by SlidesCarnival
Presentation models by SlideModel
Erlang by Ericsson, RabbitMQ from Pivotal & Ejabberd from ProcessOne