Share via


조직 참조

조직에 대한 메서드를 호출하기 전에 먼저 해당 조직에 대한 참조가 필요합니다. 조직 참조는 해당 조직 클래스와 동일한 조직 인터페이스를 구현하는 프록시 개체입니다. 대상 조직의 논리적 ID(형식 및 고유 키)를 캡슐화합니다. 조직 참조는 대상 조직을 호출하는 데 사용됩니다. 각 조직 참조는 단일 조직(조직 클래스의 단일 인스턴스)에 대한 것이지만 동일한 조직에 대해 여러 개의 독립적인 조직을 만들 수 있습니다.

조직 참조는 대상 조직의 논리적 ID를 나타내기 때문에 해당 조직의 물리적 위치와 독립적이며 시스템을 완전히 다시 시작한 후에도 유효한 상태를 유지합니다. 개발자는 다른 .NET 개체와 마찬가지로 조직 참조를 사용할 수 있습니다. 메서드에 전달되어 메서드 반환 값으로 사용하며 영구 스토리지에 저장할 수도 있습니다.

조직 참조는 조직의 ID를 IGrainFactory.GetGrain<TGrainInterface>(Type, Guid) 메서드에 전달하여 얻을 수 있습니다. 여기서 T는 조직 인터페이스이고 key는 형식 내의 조직 고유 키입니다.

다음은 위에서 정의한 IPlayerGrain 인터페이스의 조직 참조를 가져오는 방법의 예입니다.

조직 클래스 내에서:

// This would typically be read from an HTTP request parameter or elsewhere.
Guid playerId = Guid.NewGuid();
IPlayerGrain player = GrainFactory.GetGrain<IPlayerGrain>(playerId);

Orleans 클라이언트 코드에서:

// This would typically be read from an HTTP request parameter or elsewhere.
Guid playerId = Guid.NewGuid();
IPlayerGrain player = client.GetGrain<IPlayerGrain>(playerId);

조직 참조에는 세 가지 정보가 포함됩니다.

  1. 조직 클래스를 고유하게 식별하는 조직 형식.
  2. 해당 조직 클래스의 논리적 인스턴스를 고유하게 식별하는 조직 .
  3. 조직 참조가 구현해야 하는 인터페이스.

참고 항목

조직 형식조직 ID를 형성합니다.

위의 IGrainFactory.GetGrain 호출은 세 가지 중 두 가지만 수락했습니다.

  • 조직 참조 IPlayerGrain에 의해 구현된 인터페이스.
  • playerId의 값인 조직 .

조직 참조에 조직 형식, 인터페이스가 포함되어 있음에도 불구하고 이러한 예에서는 인터페이스와 함께 Orleans만 제공했습니다. 이는 Orleans가 조직 인터페이스와 조직 형식 간의 매핑을 유지하기 때문입니다. 조직 팩터리에 IShoppingCartGrain을 요청하면 Orleans는 매핑을 참조하여 참조를 만들 수 있도록 해당 조직 형식을 찾습니다. 이는 조직 인터페이스 구현이 하나만 있는 경우에 작동하지만 구현이 여러 개인 경우 GetGrain 호출에서 이를 명확하게 해야 합니다. 자세한 내용은 다음 섹션인 명확한 조직 형식 구분 확인을 참조하세요.

참고 항목

Orleans는 컴파일 중에 애플리케이션의 각 조직 인터페이스에 대한 조직 참조 구현 형식을 생성합니다. 이러한 조직 참조 구현은 Orleans.Runtime.GrainReference 클래스에서 상속됩니다. GetGrain은 요청된 조직 인터페이스에 해당하는 생성된 Orleans.Runtime.GrainReference 구현의 인스턴스를 반환합니다.

명확한 조직 형식 구분 확인

다음 예와 같이 조직 인터페이스의 구현이 여러 개 있는 경우 Orleans는 조직 참조를 만들 때 의도한 구현을 결정하려고 시도합니다. ICounterGrain 인터페이스의 두 가지 구현이 있는 다음 예를 고려해 보세요.

public interface ICounterGrain : IGrainWithStringKey
{
    ValueTask<int> UpdateCount();
}

public class UpCounterGrain : ICounterGrain
{
    private int _count;

    public ValueTask<string> UpdateCount() => new(++_count); // Increment count
}

public class DownCounterGrain : ICounterGrain
{
    private int _count;

    public ValueTask<string> UpdateCount() => new(--_count); // Decrement count
}

GetGrain에 대한 다음 호출은 Orleans가 ICounterGrain을 조직 클래스 중 하나에 명확하게 매핑하는 방법을 모르기 때문에 예외를 throw합니다.

// This will throw an exception: there is no unambiguous mapping from ICounterGrain to a grain class.
ICounterGrain myCounter = grainFactory.GetGrain<ICounterGrain>("my-counter");

다음 메시지와 함께 System.ArgumentException이 throw됩니다.

Unable to identify a single appropriate grain type for interface ICounterGrain. Candidates: upcounter (UpCounterGrain), downcounter (DownCounterGrain)

오류 메시지는 요청된 조직 인터페이스 형식인 ICounterGrain과 일치하는 조직 구현의 Orleans를 알려 줍니다. 조직 형식 이름(upcounterdowncounter)과 조직 클래스(UpCounterGrainDownCounterGrain)가 표시됩니다.

참고 항목

이전 오류 메시지의 조직 형식 이름인 upcounterdowncounter는 각각 조직 클래스 이름인 UpCounterGrainDownCounterGrain에서 파생됩니다. 이는 Orleans의 기본 동작이며 조직 클래스에 [GrainType(string)] 특성을 추가하여 사용자 지정할 수 있습니다. 예시:

[GrainType("up")]
public class UpCounterGrain : IUpCounterGrain { /* as above */ }

이 모호성을 해결하는 방법에는 다음 하위 섹션에 자세히 설명되어 있습니다.

고유한 마커 인터페이스를 사용하여 명확한 조직 형식 구분

이러한 조직을 명확하게 구분하는 가장 명확한 방법은 고유한 조직 인터페이스를 제공하는 것입니다. 예를 들어, 다음 예와 같이 IUpCounterGrain 인터페이스를 UpCounterGrain 클래스에 추가하고 IDownCounterGrain 인터페이스를 DownCounterGrain 클래스에 추가하면 모호한 ICounterGrain 형식을 전달하는 대신 IUpCounterGrain 또는 IDownCounterGrainGetGrain<T> 호출에 전달하여 올바른 조직 참조를 확인할 수 있습니다.

public interface ICounterGrain : IGrainWithStringKey
{
    ValueTask<int> UpdateCount();
}

// Define unique interfaces for our implementations
public interface IUpCounterGrain : ICounterGrain, IGrainWithStringKey {}
public interface IDownCounterGrain : ICounterGrain, IGrainWithStringKey {}

public class UpCounterGrain : IUpCounterGrain
{
    private int _count;

    public ValueTask<string> UpdateCount() => new(++_count); // Increment count
}

public class DownCounterGrain : IDownCounterGrain
{
    private int _count;

    public ValueTask<string> UpdateCount() => new(--_count); // Decrement count
}

두 조직에 대한 참조를 만들려면 다음 코드를 고려해 보세요.

// Get a reference to an UpCounterGrain.
ICounterGrain myUpCounter = grainFactory.GetGrain<IUpCounterGrain>("my-counter");

// Get a reference to a DownCounterGrain.
ICounterGrain myDownCounter = grainFactory.GetGrain<IDownCounterGrain>("my-counter");

참고 항목

앞의 예에서는 키는 동일하지만 조직 형식이 다른 두 개의 조직 참조를 만들었습니다. myUpCounter 변수에 저장된 첫 번째는 ID가 upcounter/my-counter인 조직에 대한 참조입니다. myDownCounter 변수에 저장된 두 번째는 ID가 downcounter/my-counter인 조직에 대한 참조입니다. 이는 조직을 고유하게 식별하는 조직 형식과 조직 의 조합입니다. 따라서 myUpCountermyDownCounter는 서로 다른 입자를 나타냅니다.

조직 클래스 접두사를 제공하여 명확한 조직 형식 구분

예를 들어, IGrainFactory.GetGrain에 조직 클래스 이름 접두사를 제공할 수 있습니다.

ICounterGrain myUpCounter = grainFactory.GetGrain<ICounterGrain>("my-counter", grainClassNamePrefix: "Up");
ICounterGrain myDownCounter = grainFactory.GetGrain<ICounterGrain>("my-counter", grainClassNamePrefix: "Down");

명명 규칙을 사용하여 기본 조직 구현 지정

동일한 조직 인터페이스의 여러 구현을 명확하게 구분하는 경우 Orleans는 인터페이스 이름에서 선행 'I'를 제거하는 규칙을 사용하여 구현을 선택합니다. 예를 들어, 인터페이스 이름이 ICounterGrain이고 두 가지 구현(CounterGrainDownCounterGrain)이 있는 경우 다음 예와 같이 ICounterGrain에 대한 참조를 요청하면 Orleans는 CounterGrain을 선택합니다.

/// This will refer to an instance of CounterGrain, since that matches the convention.
ICounterGrain myUpCounter = grainFactory.GetGrain<ICounterGrain>("my-counter");

특성을 사용하여 기본 조직 형식 지정

다음 예와 같이 조직 인터페이스에 Orleans.Metadata.DefaultGrainTypeAttribute 특성을 추가하여 해당 인터페이스에 대한 기본 구현의 조직 형식을 지정할 수 있습니다.

[DefaultGrainType("up-counter")]
public interface ICounterGrain : IGrainWithStringKey
{
    ValueTask<int> UpdateCount();
}

[GrainType("up-counter")]
public class UpCounterGrain : ICounterGrain
{
    private int _count;

    public ValueTask<string> UpdateCount() => new(++_count); // Increment count
}

[GrainType("down-counter")]
public class DownCounterGrain : ICounterGrain
{
    private int _count;

    public ValueTask<string> UpdateCount() => new(--_count); // Decrement count
}
/// This will refer to an instance of UpCounterGrain, due to the [DefaultGrainType("up-counter"')] attribute
ICounterGrain myUpCounter = grainFactory.GetGrain<ICounterGrain>("my-counter");

확인된 조직 ID를 제공하여 명확한 조직 형식 구분

IGrainFactory.GetGrain의 일부 오버로드는 Orleans.Runtime.GrainId 형식의 인수를 허용합니다. 이러한 오버로드를 사용할 때 Orleans는 인터페이스 형식에서 조직 형식으로 매핑할 필요가 없으므로 해결해야 할 모호성이 없습니다. 예시:

public interface ICounterGrain : IGrainWithStringKey
{
    ValueTask<int> UpdateCount();
}

[GrainType("up-counter")]
public class UpCounterGrain : ICounterGrain
{
    private int _count;

    public ValueTask<string> UpdateCount() => new(++_count); // Increment count
}

[GrainType("down-counter")]
public class DownCounterGrain : ICounterGrain
{
    private int _count;

    public ValueTask<string> UpdateCount() => new(--_count); // Decrement count
}
// This will refer to an instance of UpCounterGrain, since "up-counter" was specified as the grain type
// and the UpCounterGrain uses [GrainType("up-counter")] to specify its grain type.
ICounterGrain myUpCounter = grainFactory.GetGrain<ICounterGrain>(GrainId.Create("up-counter", "my-counter"));