Hostowanie za pomocą usługi Service Fabric
Orleans program może być hostowany w usłudze Azure Service Fabric przy użyciu usług Microsoft.ServiceFabric.Services i Microsoft.Orleans. Pakiety NuGet serwera . Silosy powinny być hostowane jako niepartycyjne, bezstanowe usługi, ponieważ Orleans zarządza rozkładem samych ziarna. Inne opcje hostingu, takie jak partycjonowane i stanowe, są bardziej złożone i nie dają żadnych korzyści bez dodatkowego dostosowania ze strony dewelopera. Zaleca się hostowanie Orleans bezpartyjnych i bezstanowych.
Usługa Service Fabric bezstanowa jako silos
Niezależnie od tego, czy tworzysz nową aplikację usługi Service Fabric, czy dodajesz Orleans ją do istniejącej, będziesz potrzebować odwołań do Microsoft.ServiceFabric.Services
pakietu i Microsoft.Orleans.Server
w projekcie. Projekt usługi bezstanowej wymaga implementacji w ICommunicationListener podklasie i klasy StatelessService.
Cykl życia silosu jest zgodny z typowym cyklem życia odbiornika komunikacji:
- Jest on inicjowany za pomocą polecenia ICommunicationListener.OpenAsync.
- Jest ona bezpiecznie zakończona za pomocą ICommunicationListener.CloseAsyncpolecenia .
- Albo nagle kończy się to ciągiem ICommunicationListener.Abort.
Ponieważ Orleans silosy są w stanie żyć w granicach IHost, implementacja ICommunicationListener
jest otoką wokół IHost
. Element IHost
jest inicjowany w metodzie OpenAsync
i bezpiecznie zakończony w metodzie CloseAsync
:
ICommunicationListener |
IHost Interakcje |
---|---|
OpenAsync | Wystąpienie IHost jest tworzone i wykonywane jest wywołanie StartAsync metody . |
CloseAsync | Oczekuje się wywołania StopAsync metody w wystąpieniu hosta. |
Abort | Wywołanie metody StopAsync jest siłowo oceniane za pomocą GetAwaiter().GetResult() polecenia . |
Obsługa klastra
Oficjalna obsługa klastrowania jest dostępna w różnych pakietach, w tym:
- Microsoft.Orleans. Clustering.AzureStorage
- Microsoft.Orleans. Clustering.AdoNet
- Microsoft.Orleans. Clustering.DynamoDB
Istnieje również kilka pakietów innych firm dostępnych dla innych usług, takich jak CosmosDB, Kubernetes, Redis i Aerospike. Aby uzyskać więcej informacji, zobacz Zarządzanie klastrem w programie Orleans.
Przykładowy projekt
W projekcie usługi bezstanowej zaimplementuj ICommunicationListener
interfejs, jak pokazano w poniższym przykładzie:
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;
}
}
}
Klasa HostedServiceCommunicationListener
akceptuje parametr konstruktora Func<Task<IHost>> createHost
. Zostanie on później użyty do utworzenia IHost
wystąpienia w metodzie OpenAsync
.
Następną częścią projektu usługi bezstanowej jest zaimplementowanie StatelessService
klasy . W poniższym przykładzie przedstawiono podklasę StatelessService
klasy:
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));
}
}
W poprzednim przykładzie OrleansHostedStatelessService
klasa jest odpowiedzialna za uzyskanie ICommunicationListener
wystąpienia. Metoda jest wywoływana CreateServiceInstanceListeners
przez środowisko uruchomieniowe usługi Service Fabric podczas inicjowania usługi.
Ściągając te dwie klasy razem, w poniższym przykładzie przedstawiono kompletny projekt usługi bezstanowej Program.cs pliku:
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();
}
Powyższy kod:
- Metoda ServiceRuntime.RegisterServiceAsync rejestruje klasę
OrleansHostedStatelessService
w środowisku uruchomieniowym usługi Service Fabric. - Delegat
CreateHostAsync
jest używany do tworzeniaIHost
wystąpienia.