[Elixir]SupervisorとWorkerの再起動の振る舞いをちょろっと見てみた

ちょろっとしたお遊び程度ですが、Supervisorによって管理されているプロセスをkillしたりしてプロセスをみてみました。書籍には載っているのですが、特に何も見ずにお遊び程度にサラでやってみたのでそのメモ、みたいな感じです。

初めに…

空のsupervisorプロジェクトを作ります。

$ mix new SupervisorTest --sup
$ cd SupervisorTest
$ mkdir lib/supervisor_test

$vim lib/supervisor_test/neko_supervisor.ex

defmodule SupervisorTest.Neko do
  use GenServer

  def start_link(opts) do
    {_, name} = opts
    GenServer.start_link(__MODULE__, :ok, [name: name])
  end
end

$ vim lib/supervisor_test.ex

defmodule SupervisorTest do
  use Application

  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    children = [
      worker(SupervisorTest.Neko, [name: :neko]) # 追加
    ]

    opts = [strategy: :one_for_one, name: SupervisorTest.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

Supervisorの確認

Supervisor.count_children/1 を使い、親のSupervisorのしたに :neko の子workerがぶら下がっていることを確認してみます。

iex> pid = Process.whereis :SupervisorTest.Supervisor
#PID<0.99.0>
iex> Supervisor.count_children pid
%{active: 1, specs: 1, supervisors: 0, workers: 1}
iex> Supervisor.which_children pid
[{SupervisorTest.Neko, #PID<0.100.0>, :worker, [SupervisorTest.Neko]}]

workerをexitしてみる

Supervisorの one_for_one では、監視対象のプロセスが終了したら、異なるPIDを持つプロセスを起動する、というstrategyでした。Supervisorをexitしてみて、その挙動を実際に確認してみます。

iex> {_, c_pid, _, _} = Supervisor.which_children(pid) |> hd
{SupervisorTest.Neko, #PID<0.100.0>, :worker, [SupervisorTest.Neko]}
iex> Process.exit c_pid, :kill
:neko
true

Supervisorにぶら下がる子workerをみる

ここで、親のSupervisorのPIDを元に、そのしたにぶら下がっているプロセスをみてみます。

iex> Supervisor.which_children pid
[{SupervisorTest.Neko, #PID<0.107.0>, :worker, [SupervisorTest.Neko]}]

1回exitした one_for_one の子プロセスである :neko 、exitしたら再度立ち上げられていますね。ちゃんと、PIDが異なる値になって、別プロセスが立ち上がっていることも確認できました。なるほど。

子プロセスを終了させる、という意味だと、Supervisor.terminate_child/2 もあるのですが、こちらはSupervisorから終了させるので、停止させたら復活しませんでした。その後、Supervisor.restart_child/2 で再び動き始めます。なるほど。

One More Thing

Supervisorをkillしてみます。すると、Supervisorの子も全て終了していることがわかります。まぁ、そうですよね。

iex> Process.exit pid, :kill
true
14:18:54.404 [info]  Application supervisor_test exited: killed
iex> Process.alive? pid
false
iex> Process.alive? c_pid
false
iex> Process.whereis :SupervisorTest.Supervisor
nil
iex> Process.whereis :neko
nil

このようにSupervisorが落ちるとその子も落ちるので、Supervisorを階層でつなげて、それぞれに対しても様々なstrategyを設定できるようにすることが大事ですね。そこらへんの設計が大事で難しい、という話もElixir in Actionで触れられてたなー。

分散環境はやっぱり大局的な設計はすごく大事。

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s