곡물 개발
곡물 클래스를 구현하는 코드를 작성하기 전에 .NET Standard 또는 .NET Core(기본 설정) 또는 .NET Framework 4.6.1 이상을 대상으로 하는 새 클래스 라이브러리 프로젝트를 만듭니다(종속성으로 인해 .NET Standard 또는 .NET Core를 사용할 수 없는 경우). 구현에서 인터페이스를 더 잘 분리하기 위해 동일한 클래스 라이브러리 프로젝트 또는 두 개의 서로 다른 프로젝트에서 곡물 인터페이스 및 곡물 클래스를 정의할 수 있습니다. 두 경우 모두 프로젝트는 Microsoft.Orleans.Sdk NuGet 패키지를 참조해야 합니다.
자세한 지침은 Tutorial One - Orleans Basics프로젝트 설정 섹션을 참조하세요.
그레인 인터페이스 및 클래스
곡물은 서로 상호 작용하고 각 곡물 인터페이스의 일부로 선언된 메서드를 호출하여 외부에서 호출됩니다. 곡물 클래스는 이전에 선언된 하나 이상의 곡물 인터페이스를 구현합니다. 곡물 인터페이스의 모든 메서드는 Task(void
메서드의 경우), Task<TResult> 또는 ValueTask<TResult> 반환해야 합니다(T
형식의 값을 반환하는 메서드의 경우).
다음은 Orleans 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;
}
}
그레인 메서드에 대한 응답 시간 제한
Orleans 런타임을 사용하면 그레인 메서드당 응답 시간 제한을 적용할 수 있습니다. 시간 제한 내에서 grain 메서드가 완료되지 않으면 런타임은 TimeoutException예외를 발생시킵니다. 응답 시간 제한을 적용하려면 인터페이스의 그레인 메서드 정의에 ResponseTimeoutAttribute
추가합니다. 클라이언트와 사일로 모두 시간 제한을 인식해야 하므로 속성은 그레인 클래스의 메서드 구현이 아니라 인터페이스 메서드 정의에 추가하는 것이 중요합니다.
이전 PlayerGrain
구현을 확장한 다음 예제에서는 LeaveGame
메서드에 응답 시간 제한을 적용하는 방법을 보여 있습니다.
public interface IPlayerGrain : IGrainWithGuidKey
{
Task<IGameGrain> GetCurrentGame();
Task JoinGame(IGameGrain game);
[ResponseTimeout("00:00:05")] // 5s timeout
Task LeaveGame(IGameGrain game);
}
앞의 코드는 LeaveGame
메서드에서 응답 시간 제한을 5초로 설정합니다. 게임을 종료할 때 5초보다 오래 걸리면 TimeoutException가 발생됩니다.
응답 시간 제한 구성
개별 곡물 메서드 응답 시간 제한과 마찬가지로 모든 곡물 메서드에 대한 기본 응답 시간 제한을 구성할 수 있습니다. 지정된 기간 내에 응답을 받지 못하면 그레인 메서드 호출이 시간 초과됩니다. 기본적으로 이 기간은 30초. 기본 응답 시간 제한을 구성할 수 있습니다.
- 외부 클라이언트에서 ClientMessagingOptions에서 ResponseTimeout을 구성합니다.
- 서버의 SiloMessagingOptions에 ResponseTimeout을(를) 구성합니다.
Orleans구성에 대한 자세한 내용은 클라이언트 구성 또는 서버 구성참조하세요.
그레인 메서드에서 값 반환
T
형식의 값을 반환하는 grain 메서드는 Task<T>
반환하는 것으로 그레인 인터페이스에 정의됩니다.
async
키워드로 표시되지 않은 grain 메서드의 경우 반환 값을 사용할 수 있는 경우 일반적으로 다음 문을 통해 반환됩니다.
public Task<SomeType> GrainMethod1()
{
return Task.FromResult(GetSomeType());
}
값을 반환하지 않는, 즉 void 메서드인 grain 메서드는 grain 인터페이스에서 Task
을 반환하는 것으로 정의됩니다. 반환된 Task
메서드의 비동기 실행 및 완료를 나타냅니다.
async
키워드로 표시되지 않은 grain 메서드의 경우 "void" 메서드가 실행을 완료하면 Task.CompletedTask특수 값을 반환해야 합니다.
public Task GrainMethod2()
{
return Task.CompletedTask;
}
async
표시된 grain 메서드는 값을 직접 반환합니다.
public async Task<SomeType> GrainMethod3()
{
return await GetSomeTypeAsync();
}
값이 반환되지 않는 async
표시된 void
grain 메서드는 실행이 끝날 때 반환됩니다.
public async Task GrainMethod4()
{
return;
}
grain 메서드가 다른 비동기 메서드 호출에서, 그레인이건 아니건, 반환 값을 수신하고 해당 호출의 오류 처리를 수행할 필요가 없는 경우, 그 비동기 호출에서 수신하는 Task
을 그대로 반환할 수 있습니다.
public Task<SomeType> GrainMethod5()
{
Task<SomeType> task = CallToAnotherGrain();
return task;
}
마찬가지로, void
grain 메서드는 대기하는 대신 다른 호출을 통해 받은 Task
을 반환할 수 있습니다.
public Task GrainMethod6()
{
Task task = CallToAsyncAPI();
return task;
}
ValueTask<T>
Task<T>
대신 사용할 수 있습니다.
곡물 참조
Grain 참조는 해당 grain 클래스와 동일한 곡물 인터페이스를 구현하는 프록시 개체입니다. 대상 그레인의 논리적 정체성(형식 및 고유 키)을 캡슐화합니다. 곡물 참조는 대상 곡물을 호출하는 데 사용됩니다. 각 곡물 참조는 단일 곡물(곡물 클래스의 단일 인스턴스)에 대한 것이지만 동일한 곡물에 대한 여러 개의 독립적인 참조를 만들 수 있습니다.
곡물 참조는 대상 곡물의 논리적 ID를 나타내므로 곡물의 물리적 위치와 독립적이며 시스템을 완전히 다시 시작한 후에도 유효한 상태를 유지합니다. 개발자는 다른 .NET 개체와 같은 곡물 참조를 사용할 수 있습니다. 메서드에 전달되고, 메서드 반환 값 등으로 사용되며, 영구 스토리지에 저장할 수도 있습니다.
곡물 참조는 IGrainFactory.GetGrain<TGrainInterface>(Type, Guid) 메서드에 곡물의 ID를 전달하여 얻을 수 있습니다. 여기서 T
곡물 인터페이스이고 key
형식 내의 곡물 고유 키입니다.
다음은 위에서 정의한 IPlayerGrain
인터페이스의 곡물 참조를 가져오는 방법의 예입니다.
그레인 클래스 내에서:
IPlayerGrain player = GrainFactory.GetGrain<IPlayerGrain>(playerId);
Orleans 클라이언트 코드에서.
IPlayerGrain player = client.GetGrain<IPlayerGrain>(playerId);
곡물 참조에 대한 자세한 내용은 곡물 참조 문서를 참조하세요.
Grain 메서드 호출
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.
오류 전파
grain 메서드에서 예외가 발생하면 Orleans는 필요에 따라 그 예외를 호출 스택을 따라 상위로 전파하고, 호스트 간에도 전파합니다. 의도한 대로 작동하려면 Orleans 예외를 직렬화할 수 있어야 하며 예외를 처리하는 호스트에는 예외 유형을 사용할 수 있어야 합니다. 예외 유형을 사용할 수 없는 경우 예외가 Orleans.Serialization.UnavailableExceptionFallbackException인스턴스로 throw되어 원래 예외의 메시지, 형식 및 스택 추적이 유지됩니다.
그레인 메서드에서 던져진 예외는 Orleans.Storage.InconsistentStateException에서 상속된 경우가 아니면 그레인을 비활성화시키지 않습니다.
InconsistentStateException
은 스토리지 작업 중에 발생하며, 이 작업은 그레인의 메모리 내 상태가 데이터베이스의 상태와 일치하지 않음을 발견할 때 발생합니다. 이 동작은 InconsistentStateException
의 대/소문자 구분 처리 외에도 .NET 개체에서 예외를 발생시키는 것과 유사합니다. 그 결과, 예외 때문에 개체가 제거되지는 않습니다.
가상 메서드
클래스의 그래인은 필요에 따라 OnActivateAsync과 OnDeactivateAsync 가상 메서드를 재정의할 수 있습니다. 이러한 메서드는 클래스의 각 그래인 활성화 및 비활성화 시 Orleans 런타임에 의해 호출됩니다. 이렇게 하면 곡물 코드에서 추가 초기화 및 정리 작업을 수행할 수 있습니다.
OnActivateAsync
에 의해 던져진 예외가 활성화 프로세스를 실패하게 만듭니다.
재정의된 경우 OnActivateAsync
항상 곡물 활성화 프로세스의 일부로 호출되지만 OnDeactivateAsync
서버 오류 또는 기타 비정상적인 이벤트와 같은 모든 상황에서 호출되도록 보장되지는 않습니다. 따라서 애플리케이션은 상태 변경의 지속성과 같은 중요한 작업을 수행하기 위해 OnDeactivateAsync
의존해서는 안 됩니다. 최선의 노력을 다하는 작업에만 사용해야 합니다.
또한 참조하십시오
.NET