Hosten met Service Fabric
Orleanskan worden gehost in Azure Service Fabric met behulp van Microsoft.ServiceFabric.Services en Microsoft.Orleans. NuGet-pakketten serveren. Silo's moeten worden gehost als niet-gepartitioneerde, staatloze services, omdat Orleans de distributie van graan zelf wordt beheerd. Andere hostingopties, zoals gepartitioneerd en stateful, zijn complexer en leveren geen voordelen op zonder extra aanpassingen van de ontwikkelaar. Het wordt aanbevolen om ongepartitioneerd en staatloos te hosten Orleans .
Service Fabric stateless service als silo
Of u nu een nieuwe Service Fabric-toepassing maakt of toevoegt aan Orleans een bestaande toepassing, u hebt zowel de als pakketverwijzingen Microsoft.ServiceFabric.Services
Microsoft.Orleans.Server
in uw project nodig. Het staatloze serviceproject heeft een implementatie nodig op de ICommunicationListener en subklasse van de StatelessService.
De silolevenscyclus volgt de typische levenscyclus van de communicatielistener:
- Het is geïnitialiseerd met ICommunicationListener.OpenAsync.
- Het wordt correct beëindigd met ICommunicationListener.CloseAsync.
- Of het is plotseling beëindigd met ICommunicationListener.Abort.
Aangezien Orleans Silo's in staat zijn om binnen de grenzen van de IHost, de uitvoering van de ICommunicationListener
is een wrapper rond de IHost
. De IHost
wordt geïnitialiseerd in de OpenAsync
methode en wordt correct beëindigd in de CloseAsync
methode:
ICommunicationListener |
IHost Interacties |
---|---|
OpenAsync | Het IHost exemplaar wordt gemaakt en er wordt een aanroep uitgevoerd StartAsync . |
CloseAsync | Er wordt een aanroep van StopAsync het hostexemplaren verwacht. |
Abort | Een aanroep naar StopAsync wordt geforceerd geëvalueerd, met GetAwaiter().GetResult() . |
Clusterondersteuning
Officiële clusterondersteuning is beschikbaar via verschillende pakketten, waaronder:
- Microsoft.Orleans. Clustering.AzureStorage
- Microsoft.Orleans. Clustering.AdoNet
- Microsoft.Orleans. Clustering.DynamoDB
Er zijn ook verschillende pakketten van derden beschikbaar voor andere services, zoals CosmosDB, Kubernetes, Redis en Aerospike. Zie Clusterbeheer in Orleansvoor meer informatie.
Voorbeeldproject
Implementeer in het staatloze serviceproject de ICommunicationListener
interface, zoals wordt weergegeven in het volgende voorbeeld:
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;
}
}
}
De HostedServiceCommunicationListener
klasse accepteert een Func<Task<IHost>> createHost
constructorparameter. Dit wordt later gebruikt om het IHost
exemplaar in de OpenAsync
methode te maken.
Het volgende deel van het staatloze serviceproject is het implementeren van de StatelessService
klasse. In het volgende voorbeeld ziet u de subklasse van de StatelessService
klasse:
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));
}
}
In het voorgaande voorbeeld is de klasse verantwoordelijk voor het OrleansHostedStatelessService
opleveren van een ICommunicationListener
exemplaar. De CreateServiceInstanceListeners
methode wordt aangeroepen door de Service Fabric-runtime wanneer de service wordt geïnitialiseerd.
Als u deze twee klassen samenhaalt, ziet u in het volgende voorbeeld het volledige stateless serviceproject Program.cs bestand:
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();
}
In de voorgaande code:
- De ServiceRuntime.RegisterServiceAsync methode registreert de
OrleansHostedStatelessService
klasse bij de Service Fabric-runtime. - De
CreateHostAsync
gemachtigde wordt gebruikt om hetIHost
exemplaar te maken.