Service Fabric ile konak oluşturma

OrleansMicrosoft.ServiceFabric.Services ve MicrosoftOrleans.. kullanılarak Azure Service Fabric'te barındırılabilir. Sunucu NuGet paketleri. Silolar, tanelerin dağıtımını yönettiğinden Orleans bölümlenmemiş, durum bilgisi olmayan hizmetler olarak barındırılmalıdır. Bölümlenmiş ve durum bilgisi olan diğer barındırma seçenekleri daha karmaşıktır ve geliştiricinin ek özelleştirmesi olmadan hiçbir avantaj sağlamaz. Bölümlenmemiş ve durum bilgisi olmayanları barındırmak Orleans önerilir.

Silo olarak Service Fabric durum bilgisi olmayan hizmet

İster yeni bir Service Fabric Uygulaması oluştururken ister var olan bir uygulamaya eklerken Orleans projenizde hem hem de Microsoft.ServiceFabric.ServicesMicrosoft.Orleans.Server paket başvurularına ihtiyacınız olacaktır. Durum bilgisi olmayan hizmet projesi, ICommunicationListener ve alt sınıfında StatelessServicebir uygulamaya ihtiyaç duyar.

Silo yaşam döngüsü tipik iletişim dinleyicisi yaşam döngüsünü izler:

Orleans Silolar sınırları içinde IHostyaşayabileceğinden, uygulamasının ICommunicationListener uygulaması çevresinde IHostbir sarmalayıcıdır. IHost yönteminde OpenAsync başlatılır ve yönteminde düzgün bir şekilde sonlandırılırCloseAsync:

ICommunicationListener IHost Etkileşim
OpenAsync Örnek IHost oluşturulur ve çağrısı StartAsync yapılır.
CloseAsync Konak örneğinde çağrısı StopAsync bekleniyor.
Abort çağrısı StopAsync , ile GetAwaiter().GetResult()zorla değerlendirilir.

Küme desteği

Resmi kümeleme desteği aşağıdakiler dahil olmak üzere çeşitli paketlerden kullanılabilir:

CosmosDB, Kubernetes, Redis ve Aerospike gibi diğer hizmetler için de çeşitli üçüncü taraf paketleri mevcuttur. Daha fazla bilgi için bkz. içinde Orleansküme yönetimi.

Örnek proje

Durum bilgisi olmayan hizmet projesinde ICommunicationListener aşağıdaki örnekte gösterildiği gibi arabirimini uygulayın:

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 sınıfı bir Func<Task<IHost>> createHost oluşturucu parametresi kabul eder. Bu daha sonra yönteminde IHostOpenAsync örneği oluşturmak için kullanılır.

Durum bilgisi olmayan hizmet projesinin sonraki bölümü sınıfını StatelessService uygulamaktır. Aşağıdaki örnekte sınıfın alt sınıfı gösterilmektedir 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));
    }
}

Yukarıdaki örnekte sınıfı bir OrleansHostedStatelessService örneği teslim etme sorumluluğundadır ICommunicationListener . CreateServiceInstanceListeners Yöntemi, hizmet başlatıldığında Service Fabric çalışma zamanı tarafından çağrılır.

Aşağıdaki örnekte, bu iki sınıfın birlikte çekilmesi, durum bilgisi olmayan hizmet projesi Program.cs dosyasının tamamını gösterir:

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();
}

Önceki kodda:

  • yöntemi sınıfını ServiceRuntime.RegisterServiceAsyncOrleansHostedStatelessService Service Fabric çalışma zamanına kaydeder.
  • Temsilci CreateHostAsync örneği oluşturmak IHost için kullanılır.