Fork me on GitHub

OTP 슈퍼바이저

Some contents of this translation may be outdated.
Several major changes were applied to the original lesson since the last update.

슈퍼바이저(Supervisor)는 다른 프로세스의 감시라는 단 하나의 목적에 특화된 프로세스입니다. 자식 프로세스가 실패하면 자동으로 재시작해주는 것으로 장애에 대한 내성이 높은(Fault-tolerant) 애플리케이션을 만들 수 있게 해줍니다.

목차

설정

슈퍼바이저의 마법은 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개의 재기동 전략이 있습니다.

재시작 값

자식 프로세스의 충돌을 처리하는 방법은 여럿 있습니다.

필수 옵션은 아니며, 기본 값은 :permanent입니다.

중첩

워커 프로세스에 이어서, 슈퍼바이저를 관리(supervise)해 슈퍼바이저 트리를 생성하도록 할 수도 있습니다. 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, restart: :transient]]),
]

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

SupervisorTask.Supervisor의 중요한 차이점은 기본 재시작 전략이 :temporary (태스크를 절대 재시작하지 않음)라는 점입니다.

관리되는 태스크

슈퍼바이저가 시작된 상태에서 start_child/2 함수를 사용해서 관리되는(supervised) 태스크를 생성할 수 있습니다.

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

태스크가 도중에 정지한다면 그 즉시 재기동됩니다. 이는 받아야 할 접속이 있거나, 백그라운드 작업을 수행하는 경우에 특히 유용할 것입니다.


이 페이지 공유하기