Värd med Service Fabric
Orleans kan finnas i Azure Service Fabric med hjälp av Microsoft.ServiceFabric.Services och Microsoft.Orleans. Server NuGet-paket. Silos ska vara värd för icke-partitionerade, tillståndslösa tjänster eftersom Orleans de hanterar fördelningen av själva kornen. Andra värdalternativ, till exempel partitionerade och tillståndskänsliga, är mer komplexa och ger inga fördelar utan ytterligare anpassning från utvecklarens sida. Vi rekommenderar att du är värd Orleans för opartitionerad och tillståndslös.
Tillståndslös Service Fabric-tjänst som Silo
Oavsett om du skapar ett nytt Service Fabric-program eller lägger Orleans till ett befintligt, behöver du både paketreferenserna Microsoft.ServiceFabric.Services
och Microsoft.Orleans.Server
i projektet. Det tillståndslösa tjänstprojektet behöver en implementering av ICommunicationListener och en underklass av StatelessService.
Silo-livscykeln följer den typiska livscykeln för kommunikationslyssnare:
- Den initieras med ICommunicationListener.OpenAsync.
- Den avslutas graciöst med ICommunicationListener.CloseAsync.
- Eller så avslutas det plötsligt med ICommunicationListener.Abort.
Eftersom Orleans Silos kan leva inom gränserna för IHost, är implementeringen av ICommunicationListener
en wrapper runt IHost
. IHost
Initieras i OpenAsync
-metoden och avslutas korrekt i CloseAsync
-metoden:
ICommunicationListener |
IHost Interaktioner |
---|---|
OpenAsync | Instansen IHost skapas och ett anrop till StartAsync görs. |
CloseAsync | Ett anrop till StopAsync på värdinstansen väntar. |
Abort | Ett anrop till StopAsync utvärderas kraftfullt med GetAwaiter().GetResult() . |
Klusterstöd
Officiellt stöd för klustring är tillgängligt från olika paket, inklusive:
- Microsoft.Orleans. Clustering.AzureStorage
- Microsoft.Orleans. Clustering.AdoNet
- Microsoft.Orleans. Clustering.DynamoDB
Det finns också flera tredjepartspaket tillgängliga för andra tjänster som CosmosDB, Kubernetes, Redis och Aerospike. Mer information finns i Klusterhantering i Orleans.
Exempelprojekt
I det tillståndslösa tjänstprojektet implementerar du ICommunicationListener
gränssnittet enligt följande exempel:
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;
}
}
}
Klassen HostedServiceCommunicationListener
accepterar en Func<Task<IHost>> createHost
konstruktorparameter. Detta används senare för att skapa instansen IHost
OpenAsync
i -metoden.
Nästa del av det tillståndslösa tjänstprojektet är att implementera StatelessService
klassen. I följande exempel visas klassens StatelessService
underklass:
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));
}
}
I föregående exempel OrleansHostedStatelessService
ansvarar klassen för att ge en ICommunicationListener
instans. Metoden CreateServiceInstanceListeners
anropas av Service Fabric-körningen när tjänsten initieras.
När de här två klasserna samlas visar följande exempel det fullständiga tillståndslösa tjänstprojektet Program.cs fil:
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();
}
I koden ovan:
- Metoden ServiceRuntime.RegisterServiceAsync registrerar
OrleansHostedStatelessService
klassen med Service Fabric-körningen. - Ombudet
CreateHostAsync
används för att skapa instansenIHost
.