Hostování s využitím Service Fabric
Orleansje možné hostovat v Azure Service Fabric pomocí služeb Microsoft.ServiceFabric.Services a Microsoft.Orleans. Balíčky NuGet serveru Sila by měla být hostována jako nedílná, bezstavová služba, protože Orleans spravuje distribuci samotných zrn. Další možnosti hostování, jako jsou dělené a stavové, jsou složitější a bez dalšího přizpůsobení vývojáři nevyuplatí žádné výhody. Doporučuje se hostovat Orleans bez oddílů a bezstavové.
Bezstavová služba Service Fabric jako Silo
Bez ohledu na to, jestli vytváříte novou aplikaci Service Fabric nebo přidáváte Orleans do existující aplikace, budete potřebovat odkazy na Microsoft.Orleans.Server
Microsoft.ServiceFabric.Services
balíček i odkazy v projektu. Bezstavový projekt služby potřebuje implementaci v ICommunicationListener podtřídě StatelessServicetřídy .
Životní cyklus sila se řídí typickým životním cyklem naslouchacího procesu komunikace:
- Inicializuje se s ICommunicationListener.OpenAsync.
- Je to elegantně ukončeno s ICommunicationListener.CloseAsync.
- Nebo se náhle ukončí s ICommunicationListener.Abort.
Vzhledem k tomu Orleans , že sila jsou schopna žít v mezích IHosthranic , je provádění ICommunicationListener
obálek kolem IHost
. Inicializuje IHost
se v OpenAsync
metodě a řádně ukončena v CloseAsync
metodě:
ICommunicationListener |
IHost Interakce |
---|---|
OpenAsync | Instance IHost se vytvoří a provede se volání StartAsync . |
CloseAsync | Čeká se StopAsync volání instance hostitele. |
Abort | Volání StopAsync je vynuceně vyhodnoceno, s GetAwaiter().GetResult() . |
Podpora clusteru
Oficiální podpora clusteringu je dostupná z různých balíčků, mezi které patří:
- Microsoft.Orleans. Clustering.AzureStorage
- Microsoft.Orleans. Clustering.AdoNet
- Microsoft.Orleans. Clustering.DynamoDB
K dispozici je také několik balíčků třetích stran pro další služby, jako je CosmosDB, Kubernetes, Redis a Aerospike. Další informace naleznete v tématu Správa clusteru v Orleansnástroji .
Ukázkový projekt
V projektu bezstavové služby implementujte ICommunicationListener
rozhraní, jak je znázorněno v následujícím příkladu:
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;
}
}
}
Třída HostedServiceCommunicationListener
přijímá parametr konstruktoru Func<Task<IHost>> createHost
. To se později použije k vytvoření IHost
instance v OpenAsync
metodě.
Další částí projektu bezstavové služby je implementace StatelessService
třídy. Následující příklad ukazuje podtřídu StatelessService
třídy:
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));
}
}
V předchozím příkladu OrleansHostedStatelessService
je třída zodpovědná za výnos ICommunicationListener
instance. Metoda CreateServiceInstanceListeners
je volána modulem runtime Service Fabric při inicializaci služby.
Načtení těchto dvou tříd dohromady, následující příklad ukazuje kompletní bezstavový projekt služby Program.cs soubor:
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();
}
V předchozím kódu:
- Metoda ServiceRuntime.RegisterServiceAsync zaregistruje
OrleansHostedStatelessService
třídu v modulu runtime Service Fabric. - Delegát
CreateHostAsync
se používá k vytvořeníIHost
instance.