Task.Supervisor — 태스크용 슈퍼바이저

Task.Supervisor — 태스크용 슈퍼바이저

동시에 여러 태스크를 안전하게 감독하면서 실행하고 싶을 때 쓰는 것이 Task.Supervisor예요. 이 모듈은 태스크를 동적으로 감독하는 데 사용할 수 있는 슈퍼바이저를 정의해요.

출처: Task.Supervisor — A task supervisor

본문

태스크 슈퍼바이저는 자식이 없는 상태로 시작되며, 보통 다른 슈퍼바이저 아래에 이름을 붙여서 시작해요.

children = [
  {Task.Supervisor, name: MyApp.TaskSupervisor}
]

Supervisor.start_link(children, strategy: :one_for_one)

자식 스펙에 주는 옵션들은 start_link/1에 문서화되어 있어요. 일단 시작되면 슈퍼바이저 아래에서 태스크를 직접 시작할 수 있어요.

task = Task.Supervisor.async(MyApp.TaskSupervisor, fn ->
  :do_some_work
end)

더 자세한 예시는 Task 모듈 문서를 참고하면 돼요.

확장성과 파티셔닝(Scalability and partitioning)

Task.Supervisor다른 프로세스를 시작하는 단일 프로세스예요. 어떤 애플리케이션에서는 이 슈퍼바이저가 병목(bottleneck) 이 될 수 있어요. 이를 해결하려면 Task.Supervisor 인스턴스를 여러 개 시작하고, 태스크를 시작할 인스턴스를 무작위로 고르면 돼요.

PartitionSupervisor를 쓰면 코어마다 동적 슈퍼바이저를 기본으로 하나씩 시작하게 만들 수 있어요.

children = [
  {PartitionSupervisor,
   child_spec: Task.Supervisor,
   name: MyApp.TaskSupervisors}
]

그 다음에는 이름 대신 파티션 슈퍼바이저를 통해 {:via, PartitionSupervisor, {name, key}} 형식으로 태스크를 시작해요. 여기서 name은 파티션 슈퍼바이저 이름, key는 라우팅 키예요.

Task.Supervisor.async(
  {:via, PartitionSupervisor, {MyApp.TaskSupervisors, self()}},
  fn -> :do_some_work end
)

위 코드에서 라우팅 키로 self()를 골랐는데, 이는 각 프로세스가 기존 태스크 슈퍼바이저 중 하나에 할당된다는 뜻이에요. 더 자세한 내용은 PartitionSupervisor 문서를 보면 돼요.

이름 등록(Name registration)

Task.SupervisorGenServer같은 이름 등록 규칙을 따르므로, GenServer 문서의 이름 등록 부분을 참고하면 돼요.

더 알아보기

  • 시작: Task.Supervisor.start_link/1, Task.Supervisor.start_child/2
  • 동시 실행: Task.Supervisor.async/2, Task.Supervisor.async_nolink/2
  • 가시성·관리: Task.Supervisor.count_children/1, Task.Supervisor.which_children/1, Task.Supervisor.terminate_child/2
  • 관련 모듈: Task, PartitionSupervisor, Supervisor
  • 가이드: task-and-gen-tcp