Service Fabric을 사용한 호스트

Orleans(은)는 Microsoft.ServiceFabric.ServicesMicrosoft를 사용하여 Azure Service Fabric을 호스팅 할 수 있습니다.Orleans.서버 NuGet 패키지. Orleans(은)는 노이즈 자체 분포를 관리하므로 사일로는 분할되지 않은 상태 비저장 서비스로 호스트되어야 합니다. 분할 및 상태 저장과 같은 다른 호스팅 옵션은 더 복잡하며 개발자에 의한 추가 사용자 지정 없이는 이점을 얻을 수 없습니다. 분할되지 않고 상태 비국적 Orleans에 호스트하는 것이 좋습니다.

사일로로서의 Service Fabric 상태 비저장 서비스

새 Service Fabric 애플리케이션을 만들거나 기존 애플리케이션에 Orleans(을)를 추가하는 경우 프로젝트의 Microsoft.ServiceFabric.ServicesMicrosoft.Orleans.Server 패키지 참조가 모두 필요합니다. 상태 비저장 서비스 프로젝트에는 ICommunicationListener 구현과 StatelessService의 하위 클래스가 필요합니다.

사일로 수명 주기는 일반적인 통신 수신기 수명 주기를 따릅니다.

Orleans 사일로는 IHost 범위 내에서 살 수 있기 때문에 ICommunicationListener 구현은 IHost에 둘러싸인 래핑입니다. IHostOpenAsync 메서드에서 초기화되고 CloseAsync 메서드에서 정상적으로 종료됩니다.

ICommunicationListener IHost 상호 작용
OpenAsync IHost 인스턴스가 만들어지고 StartAsync 호출이 수행됩니다.
CloseAsync 호스트 인스턴스에서 StopAsync 호출이 대기됩니다.
Abort StopAsync 호출은 GetAwaiter().GetResult()를 사용하여 강제로 평가됩니다.

클러스터 지원

공식 클러스터링 지원은 다음을 비롯한 다양한 패키지에서 사용할 수 있습니다.

CosmosDB, Kubernetes, Redis 및 Aerospike와 같은 다른 서비스에 사용할 수 있는 여러 타사 패키지도 있습니다. 자세한 내용은 Orleans에서 클러스터 관리를 참조하세요.

예제 프로젝트

상태 비정상 서비스 프로젝트에서 다음 예제와 같이 ICommunicationListener 인터페이스를 구현합니다.

using Microsoft.Extensions.Hosting;
using Microsoft.ServiceFabric.Services.Communication.Runtime;

namespace ServiceFabric.HostingExample;

internal sealed class HostedServiceCommunicationListener : ICommunicationListener
{
    private IHost? _host;
    private readonly Func<Task<IHost>> _createHost;

    public HostedServiceCommunicationListener(Func<Task<IHost>> createHost) =>
        _createHost = createHost ?? throw new ArgumentNullException(nameof(createHost));

    /// <inheritdoc />
    public async Task<string?> OpenAsync(CancellationToken cancellationToken)
    {
        try
        {
            _host = await _createHost.Invoke();
            await _host.StartAsync(cancellationToken);
        }
        catch
        {
            Abort();
            throw;
        }

        // This service does not expose any endpoints to Service Fabric for discovery by others.
        return null;
    }

    /// <inheritdoc />
    public async Task CloseAsync(CancellationToken cancellationToken)
    {
        if (_host is { } host)
        {
            await host.StopAsync(cancellationToken);
        }

        _host = null;
    }

    /// <inheritdoc />
    public void Abort()
    {
        IHost? host = _host;
        if (host is null)
        {
            return;
        }

        using CancellationTokenSource cancellation = new();
        cancellation.Cancel(false);

        try
        {
            host.StopAsync(cancellation.Token).GetAwaiter().GetResult();
        }
        catch
        {
            // Ignore.
        }
        finally
        {
            _host = null;
        }
    }
}

HostedServiceCommunicationListener 클래스는 Func<Task<IHost>> createHost 생성자 매개 변수를 허용합니다. 이 매개 변수는 나중에 OpenAsync 메서드에서 IHost 인스턴스를 만드는 데 사용됩니다.

상태 비지정 서비스 프로젝트의 다음 부분은 StatelessService 클래스를 구현하는 것입니다. 다음 예제에서는 StatelessService 클래스의 하위 클래스를 보여줍니다.

using System.Fabric;
using Microsoft.Extensions.Hosting;
using Microsoft.ServiceFabric.Services.Communication.Runtime;
using Microsoft.ServiceFabric.Services.Runtime;

namespace ServiceFabric.HostingExample;

public sealed class OrleansHostedStatelessService : StatelessService
{
    private readonly Func<StatelessServiceContext, Task<IHost>> _createHost;

    public OrleansHostedStatelessService(
        Func<StatelessServiceContext, Task<IHost>> createHost, StatelessServiceContext serviceContext)
        : base(serviceContext) =>
        _createHost = createHost ?? throw new ArgumentNullException(nameof(createHost));  

    /// <inheritdoc/>
    protected sealed override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        // Create a listener which creates and runs an IHost
        yield return new ServiceInstanceListener(
            context => new HostedServiceCommunicationListener(() => _createHost(context)),
            nameof(HostedServiceCommunicationListener));
    }
}

앞의 예제에서 OrleansHostedStatelessService 클래스는 ICommunicationListener 인스턴스 생성을 담당합니다. CreateServiceInstanceListeners 메서드는 서비스가 초기화될 때 Service Fabric 런타임에서 호출합니다.

다음 예제에서는 이러한 두 클래스를 함께 풀링하여 완전한 상태 비저장 서비스 프로젝트 Program.cs 파일을 보여 줍니다.

using System.Fabric;
using Microsoft.Extensions.Hosting;
using Microsoft.ServiceFabric.Services.Runtime;
using ServiceFabric.HostingExample;

try
{
    // The ServiceManifest.XML file defines one or more service type names.
    // Registering a service maps a service type name to a .NET type.
    // When Service Fabric creates an instance of this service type,
    // an instance of the class is created in this host process.
    await ServiceRuntime.RegisterServiceAsync(
        "Orleans.ServiceFabric.Stateless",
        context => new OrleansHostedStatelessService(
            CreateHostAsync, context));

    ServiceEventSource.Current.ServiceTypeRegistered(
        Environment.ProcessId,
        typeof(OrleansHostedStatelessService).Name);

    // Prevents this host process from terminating so services keep running.
    await Task.Delay(Timeout.Infinite);
}
catch (Exception ex)
{
    ServiceEventSource.Current.ServiceHostInitializationFailed(
        ex.ToString());
    throw;
}

static async Task<IHost> CreateHostAsync(StatelessServiceContext context)
{
    await Task.CompletedTask;

    return Host.CreateDefaultBuilder()
        .UseOrleans((_, builder) =>
        {
            // TODO, Use real storage, something like table storage
            // or SQL Server for clustering.
            builder.UseLocalhostClustering();

            // Service Fabric manages port allocations, so update the 
            // configuration using those ports. Gather configuration from 
            // Service Fabric.
            var activation = context.CodePackageActivationContext;
            var endpoints = activation.GetEndpoints();

            // These endpoint names correspond to TCP endpoints 
            // specified in ServiceManifest.xml
            var siloEndpoint = endpoints["OrleansSiloEndpoint"];
            var gatewayEndpoint = endpoints["OrleansProxyEndpoint"];
            var hostname = context.NodeContext.IPAddressOrFQDN;
            builder.ConfigureEndpoints(hostname,
                siloEndpoint.Port, gatewayEndpoint.Port);
        })
        .Build();
}

위의 코드에서

  • ServiceRuntime.RegisterServiceAsync 메서드는 OrleansHostedStatelessService 클래스를 Service Fabric 런타임에 등록합니다.
  • CreateHostAsync 대리자는 IHost 인스턴스를 만드는 데 사용됩니다.