학습
조직 개발
조직 클래스를 구현하는 코드를 작성하기 전에 .NET Standard 또는 .NET Core(기본 설정) 또는 .NET Framework 4.6.1 이상을 대상으로 하는 새 클래스 라이브러리 프로젝트를 만듭니다(종속성으로 인해 .NET Standard 또는 .NET Core를 사용할 수 없는 경우). 구현에서 인터페이스를 더 잘 분리하기 위해 동일한 클래스 라이브러리 프로젝트 또는 두 개의 서로 다른 프로젝트에서 조직 인터페이스와 조직 클래스를 정의할 수 있습니다. 두 경우 모두 프로젝트는 Microsoft.Orleans.Core.Abstractions 및 Microsoft.Orleans.CodeGenerator.MSBuild NuGet 패키지를 참조해야 합니다.
자세한 지침은 자습서 1 – Orleans 기본 사항의 프로젝트 설정 섹션을 참조하세요.
조직은 서로 상호 작용하고 각 조직 인터페이스의 일부로 선언된 메서드를 호출하여 외부에서 호출됩니다. 조직 클래스는 이전에 선언된 하나 이상의 조직 인터페이스를 구현합니다. 조직 인터페이스의 모든 메서드는 Task(void
메서드의 경우), Task<TResult> 또는 ValueTask<TResult>(형식 T
의 값을 반환하는 메서드의 경우)를 반환해야 합니다.
다음은 Orleans 버전 1.5 Presence Service 샘플에서 발췌한 내용입니다.
public interface IPlayerGrain : IGrainWithGuidKey
{
Task<IGameGrain> GetCurrentGame();
Task JoinGame(IGameGrain game);
Task LeaveGame(IGameGrain game);
}
public class PlayerGrain : Grain, IPlayerGrain
{
private IGameGrain _currentGame;
// Game the player is currently in. May be null.
public Task<IGameGrain> GetCurrentGame()
{
return Task.FromResult(_currentGame);
}
// Game grain calls this method to notify that the player has joined the game.
public Task JoinGame(IGameGrain game)
{
_currentGame = game;
Console.WriteLine(
$"Player {GetPrimaryKey()} joined game {game.GetPrimaryKey()}");
return Task.CompletedTask;
}
// Game grain calls this method to notify that the player has left the game.
public Task LeaveGame(IGameGrain game)
{
_currentGame = null;
Console.WriteLine(
$"Player {GetPrimaryKey()} left game {game.GetPrimaryKey()}");
return Task.CompletedTask;
}
}
T
형식 값을 반환하는 조직 메서드는 조직 인터페이스에서 Task<T>
를 반환되는 형식으로 정의됩니다.
async
키워드로 표시되지 않은 조직 메서드의 경우 반환 값을 사용할 때 일반적으로 다음 명령문을 통해 반환됩니다.
public Task<SomeType> GrainMethod1()
{
return Task.FromResult(GetSomeType());
}
값을 반환하지 않고 사실상 void 메서드를 반환하는 조직 메서드는 조직 인터페이스에서 Task
를 반환하는 것으로 정의됩니다. 반환된 Task
는 메서드의 비동기 실행 및 완료를 나타냅니다. async
키워드로 표시되지 않은 조직 메서드의 경우 "void" 메서드가 실행을 완료하면 Task.CompletedTask의 특수 값을 반환해야 합니다.
public Task GrainMethod2()
{
return Task.CompletedTask;
}
async
로 표시된 조직 메서드는 값을 직접 반환합니다.
public async Task<SomeType> GrainMethod3()
{
return await GetSomeTypeAsync();
}
값이 반환되지 않는 async
로 표시된 void
조직 메서드는 실행이 끝날 때 반환됩니다.
public async Task GrainMethod4()
{
return;
}
조직 메서드가 다른 비동기 메서드 호출에서 조직으로 반환 값을 수신하고 해당 호출의 오류 처리를 수행할 필요가 없는 경우 해당 비동기 호출에서 수신한 Task
를 간단히 반환할 수 있습니다.
public Task<SomeType> GrainMethod5()
{
Task<SomeType> task = CallToAnotherGrain();
return task;
}
마찬가지로, void
조직 메서드는 대기하는 대신 다른 호출을 통해 반환된 Task
를 반환할 수 있습니다.
public Task GrainMethod6()
{
Task task = CallToAsyncAPI();
return task;
}
Task<T>
대신 ValueTask<T>
를 사용할 수 있습니다.
조직 참조는 해당 조직 클래스와 동일한 조직 인터페이스를 구현하는 프록시 개체입니다. 대상 조직의 논리적 ID(형식 및 고유 키)를 캡슐화합니다. 조직 참조는 대상 조직을 호출하는 데 사용됩니다. 각 조직 참조는 단일 조직(조직 클래스의 단일 인스턴스)에 대한 것이지만 동일한 조직에 대해 여러 개의 독립적인 조직을 만들 수 있습니다.
조직 참조는 대상 조직의 논리적 ID를 나타내기 때문에 해당 조직의 물리적 위치와 독립적이며 시스템을 완전히 다시 시작한 후에도 유효한 상태를 유지합니다. 개발자는 다른 .NET 개체와 마찬가지로 조직 참조를 사용할 수 있습니다. 메서드에 전달되어 메서드 반환 값 등으로 사용하며 영구 스토리지에 저장할 수도 있습니다.
조직 참조는 조직의 ID를 IGrainFactory.GetGrain<TGrainInterface>(Type, Guid) 메서드에 전달하여 얻을 수 있습니다. 여기서 T
는 조직 인터페이스이고 key
는 형식 내의 조직 고유 키입니다.
다음은 위에서 정의한 IPlayerGrain
인터페이스의 조직 참조를 가져오는 방법의 예입니다.
조직 클래스 내에서:
IPlayerGrain player = GrainFactory.GetGrain<IPlayerGrain>(playerId);
Orleans 클라이언트 코드에서
IPlayerGrain player = client.GetGrain<IPlayerGrain>(playerId);
Orleans 프로그래밍 모델은 비동기 프로그래밍을 기반으로 합니다. 이전 예제의 조직 참조를 사용하여 조직 메서드 호출을 수행하는 방법은 다음과 같습니다.
// Invoking a grain method asynchronously
Task joinGameTask = player.JoinGame(this);
// The await keyword effectively makes the remainder of the
// method execute asynchronously at a later point
// (upon completion of the Task being awaited) without blocking the thread.
await joinGameTask;
// The next line will execute later, after joinGameTask has completed.
players.Add(playerId);
둘 이상의 Tasks
를 조인할 수 있습니다. 조인 작업은 모든 구성 Task
가 완료될 때 해결되는 새 Task
를 만듭니다. 조직이 여러 계산을 시작하고 계속하기 전에 모든 계산이 완료되기를 기다려야 하는 경우에 유용한 패턴입니다. 예를 들어 여러 부분으로 구성된 웹 페이지를 생성하는 프런트 엔드 조직은 각 부분마다 하나씩 여러 백 엔드 호출을 수행하고 각 결과에 대해 Task
를 수신할 수 있습니다. 그러면 조직은 이 모든 Tasks
의 조인을 대기합니다. 조인 Task
가 확인되면 개별 Task
가 완료되고 웹 페이지의 서식을 지정하는 데 필요한 모든 데이터가 수신됩니다.
예:
List<Task> tasks = new List<Task>();
Message notification = CreateNewMessage(text);
foreach (ISubscriber subscriber in subscribers)
{
tasks.Add(subscriber.Notify(notification));
}
// WhenAll joins a collection of tasks, and returns a joined
// Task that will be resolved when all of the individual notification Tasks are resolved.
Task joinedTask = Task.WhenAll(tasks);
await joinedTask;
// Execution of the rest of the method will continue
// asynchronously after joinedTask is resolve.
조직 클래스는 선택적으로 OnActivateAsync 및 OnDeactivateAsync 가상 메서드를 재정의할 수 있습니다. 이러한 메서드는 클래스의 각 조직을 활성화 및 비활성화할 때 Orleans 런타임에 의해 호출됩니다. 이렇게 하면 조직 코드에서 추가 초기화 및 정리 작업을 수행할 수 있습니다. OnActivateAsync
에서 예외가 throw된 경우 활성화 프로세스가 실패합니다.
재정의되는 경우 OnActivateAsync
는 항상 조직 활성화 프로세스의 일부로 호출되지만 OnDeactivateAsync
는 예를 들어 서버 오류 또는 기타 비정상적인 이벤트와 같은 모든 상황에서 호출된다는 보장이 없습니다. 따라서 애플리케이션은 상태 변경의 지속성과 같은 중요한 작업을 수행하는 데 OnDeactivateAsync
를 사용해서는 안 됩니다. 최선의 노력을 해야 하는 작업에만 사용해야 합니다.