初學 Elixir, 我經常對 Supervisor 的概念感到疑惑. 沒有Supervisor, 程序也能正常運行, 爲何還要加上這個東西呢? 原來, 這和 Erlang 的基本信條 —— 「就讓它崩潰」 有關, 在 Erlang 中, 是沒有 try…rescue 這樣的錯誤救援機制的. 取而代之的是 Supervisor 機制, Supervisor 是一個專門用來監督進程的進程, 每當它的名下有進程出錯崩潰, Supervisor就會按照既定的策略重啓進程.網絡
咱們將 Supervisor 名下的進程叫作子進程, 將由 Supervisor 和子進程所組成的監督網絡稱爲 監督樹. 有了監督樹的幫助, 咱們能夠方便地構建一個高容錯的應用.函數
這裏要注意模塊和進程的關係. 模塊是函數的集合, 而相似 start_link
的函數能夠建立進程, rest
那麼, 如何在 phoenix 項目裏使用 Supervisor 呢? ELixir 內置了兩個模塊: Supervisor 和 Supervisor.Spec.code
Supervisor.Spec
咱們能夠這樣設置 supervisor 名下的子進程:orm
import Supervisor.Spec children = [ worker(MyWorker, [arg1, arg2, arg3]), supervisor(MySupervisor, [arg1]) # 這個 supervisor 也是子進程 ] Supervisor.start_link(children, strategy: :one_for_one)
Supervisor
這是以模塊的方式配置 supervisor, 它包含了 import Supervisor.Spec
:進程
defmodule MySupervisor do use Supervisor def start_link(arg) do Supervisor.start_link(__MODULE__, arg) # 會調用 init 回調 end def init(arg) do children = [ worker(MyWorker, [arg], restart: :temporary) ] supervise(children, strategy: :simple_one_for_one) end end
supervise(children, options)
會以tuple 的形式返回一個 supervisor配置. it
supervisor(module, args, options \ [])
將給定的模塊設置爲一個 supervisor.io
worker(module, args, options \ [])
將一個給定的模塊定義爲 worker.import
Supervisor
的主要函數count_children(supervisor)
返回一個清點子進程數的映射.delete_child(supervisor, child_id)
經過子進程的id 刪除其配置信息.restart_child(supervisor, child_id)
經過 id 重啓子進程.start_child(supervisor, child_spec_or_args)
動態添加子進程配置信息, 並啓動它.start_link(children, options)
按給定的子進程啓動一個 supervisor.start_link(module, arg, options \ [])
按給定的模塊啓動一個 supervisor .stop(supervisor, reason \ :normal, timeout \ :infinity)
中止 supervisor.terminate_child(supervisor, pid_or_child_id)
終止子進程.which_children(supervisor)
返回子進程列表.module