조직 서비스

조직 서비스는 기능 조직을 지원하기 위해 원격으로 액세스할 수 있는 분할된 서비스입니다. 조직 서비스의 각 인스턴스는 일부 조직 집합을 담당하며, 이러한 조직은 GrainServiceClient를 사용하여 현재 서비스를 담당하는 조직 서비스에 대한 참조를 얻을 수 있습니다.

조직 서비스는 Orleans 클러스터를 중심으로 조직 서비스에 대한 책임을 분산해야 하는 경우를 지원하기 위해 존재합니다. 예를 들어 Orleans 미리 알림은 조직 서비스를 사용하여 구현됩니다. 각 사일로는 조직의 하위 집합에 대한 미리 알림 작업을 처리하고 미리 알림이 실행될 때 해당 조직에 알릴 책임이 있습니다.

조직 서비스는 사일로에서 구성되며 사일로가 시작될 때 사일로 초기화 전에 초기화됩니다. 유휴 상태일 때는 수집되지 않는 대신 사일로 자체의 수명 동안 연장되는 수명을 갖습니다.

GrainService 만들기

GrainService는 안정적인 ID가 없고 시작부터 종료까지 모든 사일로에서 실행되는 특수한 조직입니다. IGrainService 인터페이스를 구현할 때는 몇 가지 단계가 필요합니다.

  1. 조직 서비스 통신 인터페이스를 정의합니다. GrainService의 인터페이스는 조직의 인터페이스를 빌드하는 데 사용하는 것과 동일한 원칙을 사용하여 빌드됩니다.

    public interface IDataService : IGrainService
    {
        Task MyMethod();
    }
    
  2. DataService 조직 서비스를 만듭니다. GrainService에서 조직 호출을 할 수 있도록 IGrainFactory를 주입하는 것입니다.

    [Reentrant]
    public class DataService : GrainService, IDataService
    {
        readonly IGrainFactory _grainFactory;
    
        public DataService(
            IServiceProvider services,
            GrainId id,
            Silo silo,
            ILoggerFactory loggerFactory,
            IGrainFactory grainFactory)
            : base(id, silo, loggerFactory)
        {
            _grainFactory = grainFactory;
        }
    
        public override Task Init(IServiceProvider serviceProvider) =>
            base.Init(serviceProvider);
    
        public override Task Start() => base.Start();
    
        public override Task Stop() => base.Stop();
    
        public Task MyMethod()
        {
            // TODO: custom logic here.
            return Task.CompletedTask;
        }
    }
    
    [Reentrant]
    public class DataService : GrainService, IDataService
    {
        readonly IGrainFactory _grainFactory;
    
        public DataService(
            IServiceProvider services,
            IGrainIdentity id,
            Silo silo,
            ILoggerFactory loggerFactory,
            IGrainFactory grainFactory)
            : base(id, silo, loggerFactory)
        {
            _grainFactory = grainFactory;
        }
    
        public override Task Init(IServiceProvider serviceProvider) =>
            base.Init(serviceProvider);
    
        public override Task Start() => base.Start();
    
        public override Task Stop() => base.Stop();
    
        public Task MyMethod()
        {
            // TODO: custom logic here.
            return Task.CompletedTask;
        }
    }
    
  3. 다른 조직에서 GrainService에 연결하는 데 사용할 GrainServiceClient<TGrainService>GrainServiceClient용 인터페이스를 만듭니다.

    public interface IDataServiceClient : IGrainServiceClient<IDataService>, IDataService
    {
    }
    
  1. 조직 서비스 클라이언트를 만듭니다. 일반적으로 클라이언트는 대상으로 하는 조직 서비스의 프록시 역할을 하므로 일반적으로 대상 서비스의 각 메서드에 대한 메서드를 추가합니다. 이러한 메서드는 호출이 가능하도록 대상으로 하는 조직 서비스에 대한 참조를 가져와야 합니다. GrainServiceClient<T> 기본 클래스는 GrainId, 숫자 해시(uint) 또는 SiloAddress에 해당하는 조직 참조를 반환할 수 있는 GetGrainService 메서드의 여러 오버로드를 제공합니다. 뒤의 두 오버로드는 개발자가 다른 메커니즘을 사용하여 호스트에 책임을 매핑하거나 호스트를 직접 처리하려는 고급 사례를 위한 것입니다. 아래 샘플 코드에서는 DataServiceClient를 호출하는 조직의 IDataService를 반환하는 속성인 GrainService를 정의합니다. 이를 위해 CurrentGrainReference 속성과 함께 GetGrainService(GrainId) 오버로드를 사용합니다.

    public class DataServiceClient : GrainServiceClient<IDataService>, IDataServiceClient
    {
        public DataServiceClient(IServiceProvider serviceProvider)
            : base(serviceProvider)
        {
        }
    
        // For convenience when implementing methods, you can define a property which gets the IDataService
        // corresponding to the grain which is calling the DataServiceClient.
        private IDataService GrainService => GetGrainService(CurrentGrainReference.GrainId);
    
        public Task MyMethod() => GrainService.MyMethod();
    }
    
  1. 실제 조직 서비스 클라이언트를 만듭니다. 데이터 서비스의 프록시 역할을 합니다. 아쉽게도 모든 메서드 매핑을 수동으로 입력해야 하는데, 간단한 한 라이너일 뿐입니다.

    public class DataServiceClient : GrainServiceClient<IDataService>, IDataServiceClient
    {
        public DataServiceClient(IServiceProvider serviceProvider)
            : base(serviceProvider)
        {
        }
    
        public Task MyMethod() => GrainService.MyMethod();
    }
    
  1. 조직 서비스 클라이언트를 필요로 하는 다른 조직에 삽입합니다. GrainServiceClient는 로컬 사일로의 GrainService에 액세스하도록 보장되지 않습니다. 클러스터의 모든 사일로에 있는 GrainService에 명령을 보낼 수 있습니다.

    public class MyNormalGrain: Grain<NormalGrainState>, INormalGrain
    {
        readonly IDataServiceClient _dataServiceClient;
    
        public MyNormalGrain(
            IGrainActivationContext grainActivationContext,
            IDataServiceClient dataServiceClient) =>
                _dataServiceClient = dataServiceClient;
    }
    
  2. 사일로에서 조직 서비스 및 조직 서비스 클라이언트를 구성합니다. 사일로가 GrainService를 시작하도록 이 작업을 수행해야 합니다.

    (ISiloHostBuilder builder) =>
        builder.ConfigureServices(
            services => services.AddGrainService<DataService>()
                                .AddSingleton<IDataServiceClient, DataServiceClient>());
    

추가적인 참고 사항

조직 서비스를 등록하는 데 사용되는 GrainServicesSiloBuilderExtensions.AddGrainService에 대한 확장 메서드가 있습니다.

services.AddSingleton<IGrainService>(
    serviceProvider => GrainServiceFactory(grainServiceType, serviceProvider));

사일로는 orleans/src/Orleans.Runtime/Silo/Silo.cs가 시작될 때 서비스 공급자에서 IGrainService 형식을 페치합니다.

var grainServices = this.Services.GetServices<IGrainService>();

Microsoft.Orleans.Runtime NuGet 패키지는 GrainService 프로젝트에서 참조되어야 합니다.

Microsoft.Orleans.Orleans런타임 NuGet 패키지는 GrainService 프로젝트에서 참조되어야 합니다.

이 작업이 작동하려면 서비스와 해당 클라이언트를 모두 등록해야 합니다. 코드는 다음과 같습니다.

var builder = new HostBuilder()
    .UseOrleans(c =>
    {
        c.AddGrainService<DataService>()  // Register GrainService
        .ConfigureServices(services =>
        {
            // Register Client of GrainService
            services.AddSingleton<IDataServiceClient, DataServiceClient>();
        });
    })