Fork me on GitHub

OTPスーパーバイザ

Supervisor(スーパーバイザ)は、他のプロセスを監視するという、1つの目的に特化したプロセスです。子プロセスが失敗した際に自動的に再起動させることによって、耐障害性の高い(フォールトトレラントな)アプリケーションを作ることを可能にします。

目次

設定

Supervisorの魔術はSupervisor.start_link関数の中にあります。スーパーバイザプロセスと子プロセスを開始するのに加えて、子を管理するためにスーパーバイザが使用する戦略を定義することができます。

子プロセスはリストと、Supervisor.Specから取り込まれたworker/3関数を使って定義されます。worker/3関数はモジュール、引数、そして一連のオプションを受け取ります。内部では、worker/3は初期化時に、与えられた引数を用いてstart_link/3を呼び出します。

OTPの並行性レッスンで実装したSimpleQueueを用いて、始めていきましょう:

import Supervisor.Spec

children = [
  worker(SimpleQueue, [], [name: SimpleQueue])
]

{:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one)

プロセスが停止したり終了させられたりすれば、スーパーバイザは何事もなかったかのように自動的にプロセスを再起動するでしょう。

戦略

今のところ、スーパーバイザが利用可能な4つの異なる再起動の戦略があります:

入れ子

ワーカープロセスに加えて、スーパーバイザーにスーパーバイザーの木構造を生成するように監督することもできます。異なるのはworker/3supervisor/3に替えることだけです:

import Supervisor.Spec

children = [
  supervisor(ExampleApp.ConnectionSupervisor, [[name: ExampleApp.ConnectionSupervisor]]),
  worker(SimpleQueue, [[], [name: SimpleQueue]])
]

{:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one)

Taskスーパーバイザ

Taskはそれ専用のスーパーバイザ、Task.Supervisorを持っています。動的にタスクを生成するために設計されており、スーパーバイザは内部では:simple_one_for_oneを用います。

セットアップ

Task.Supervisorの取り込みは、他のスーパーバイザと違いはありません:

import Supervisor.Spec

children = [
  supervisor(Task.Supervisor, [[name: ExampleApp.TaskSupervisor]]),
]

{:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one)

監督されたTask

スーパーバイザが開始された状態で、start_child/2関数を用いて監督されたタスクを作ることができます:

{:ok, pid} = Task.Supervisor.start_child(ExampleApp.TaskSupervisor, fn -> background_work end)

タスクが途中で停止する場合、再起動が行われます。これは次々と入ってくる接続や、バックグラウンド作業の処理を扱う場合には特に役に立つでしょう。


このページをシェアする