일정 예약 개요
Orleans에는 조직과 두 가지 형태의 일정 예약이 있습니다.
- 요청 예약, 요청 예약에 설명된 일정 규칙에 따라 실행을 위해 들어오는 조직 호출의 예약입니다.
- 작업 예약: 단일 스레드 방식으로 실행할 코드의 동기 블록 예약
모든 조직 코드는 조직의 작업 스케줄러에서 실행됩니다. 즉, 요청도 조직의 작업 스케줄러에서 실행됩니다. 요청 예약 규칙에서 여러 요청을 동시에 실행할 수 있더라도, 조직의 작업 스케줄러는 항상 작업을 하나씩 실행하여 병렬로 여러 작업을 실행하지 않으므로 요청이 병렬로 실행되지 않습니다.
작업 예약
일정 예약을 더 잘 이해하려면 메시지를 로그하고 잠시 기다렸다가 다른 메시지를 로그한 후 반환하는 DelayExecution()
이라는 메서드가 있는 다음 MyGrain
조직을 고려합니다.
public interface IMyGrain : IGrain
{
Task DelayExecution();
}
public class MyGrain : Grain, IMyGrain
{
private readonly ILogger<MyGrain> _logger;
public MyGrain(ILogger<MyGrain> logger) => _logger = logger;
public async Task DelayExecution()
{
_logger.LogInformation("Executing first task");
await Task.Delay(1_000);
_logger.LogInformation("Executing second task");
}
}
이 메서드를 실행하면 메서드 본문이 다음 두 부분으로 실행됩니다.
- 첫 번째
_logger.LogInformation(...)
호출과Task.Delay(1_000)
호출 - 두 번째
_logger.LogInformation(...)
호출
두 번째 작업은 Task.Delay(1_000)
호출이 완료될 때까지 조직의 작업 스케줄러에서 예약되지 않으며, 이 시점에서 조직 메서드의 연속을 예약합니다.
다음은 요청을 예약하고 두 작업으로 실행하는 방법을 그래픽으로 표현한 것입니다.
위의 설명은 Orleans에 국한되지 않으며 .NET에서 작업 일정 예약이 작동하는 방식입니다. C#의 비동기 메서드는 컴파일러에 의해 비동기 상태 컴퓨터로 변환되고 실행은 별개의 단계로 비동기 상태 컴퓨터를 통해 진행됩니다. 각 단계는 현재 TaskScheduler(TaskScheduler.Current를 통해 액세스, 기본값은 TaskScheduler.Default) 또는 현재 SynchronizationContext에서 예약됩니다. TaskScheduler
를 사용하는 경우 메서드의 각 단계는 해당 TaskScheduler
에 전달되는 Task
인스턴스로 표시됩니다. 따라서 .NET에서 Task
는 두 가지 개념적 항목을 나타낼 수 있습니다.
- 대기할 수 있는 비동기 작업입니다. 위의
DelayExecution()
메서드 실행은 대기할 수 있는Task
로 표시됩니다. - 동기 작업 블록에서 위의
DelayExecution()
메서드 내에 있는 각 단계는Task
로 표시됩니다.
TaskScheduler.Default
를 사용 중인 경우 연속 작업은 .NET ThreadPool에 직접 예약되며 Task
개체에 래핑되지 않습니다. Task
인스턴스에서 연속 작업의 래핑은 투명하게 수행되므로 개발자는 이러한 구현 세부 정보를 알 필요가 거의 없습니다.
Orleans에서 작업 예약
각 조직 활성화에는 조직의 단일 스레드 실행 모델을 적용하는 자체 TaskScheduler
인스턴스가 있습니다. 내부적으로 이 TaskScheduler
는 ActivationTaskScheduler
및 WorkItemGroup
을 통해 구현됩니다. WorkItemGroup
은 작업을 Queue<T>의 큐에 넣어 유지하고 여기서 T
는 내부적으로 Task
이며 IThreadPoolWorkItem을 구현합니다. 현재 큐에 넣은 각 Task
를 실행하기 위해 WorkItemGroup
은 .NET ThreadPool
에서 자체적으로 예약합니다. .NET ThreadPool
에서 WorkItemGroup
의 IThreadPoolWorkItem.Execute()
메서드를 호출하면 WorkItemGroup
은 큐에 넣은 Task
인스턴스를 하나씩 실행합니다.
각 조직에는 .NET ThreadPool
에서 자체적으로 예약하여 실행하는 스케줄러가 있습니다.
각 스케줄러에는 작업 큐가 포함됩니다.
.NET ThreadPool
은 큐에 넣은 각 작업 항목을 실행합니다. 여기에는 Task.Run(...)
을 통해 예약된 작업 항목과 같은 다른 작업 항목뿐만 아니라 조직 스케줄러도 포함됩니다.
참고 항목
조직의 스케줄러는 한 번에 하나의 스레드에서만 실행할 수 있지만 항상 동일한 스레드에서 실행되는 것은 아닙니다. .NET ThreadPool
은 조직의 스케줄러가 실행될 때마다 다른 스레드를 자유롭게 사용할 수 있습니다. 조직의 스케줄러는 한 번에 하나의 스레드에서만 실행되도록 하는 역할을 하며, 이것이 조직의 단일 스레드 실행 모델이 구현되는 방식입니다.
.NET