Condividi tramite


Configurazione del server

Un silo viene configurato a livello di codice con il metodo di estensione UseOrleans(IHostBuilder, Action<HostBuilderContext,ISiloBuilder>) e diverse classi di opzioni supplementari. Le classi di opzione in Orleans seguono il modello Opzioni in .NET e possono essere caricate tramite file, variabili di ambiente e qualsiasi provider di configurazione valido.

Esistono diversi aspetti chiave della configurazione del silo:

  • Provider di clustering
  • (Facoltativo) informazioni sul clustering Orleans
  • (Facoltativo) Endpoint da usare per le comunicazioni da silo a silo e da client a silo

Questo è un esempio di configurazione silo che definisce le informazioni sul cluster, usa il clustering di Azure e configura le parti dell'applicazione:

using IHost host = Host.CreateDefaultBuilder(args)
    .UseOrleans(builder =>
    {
        builder.UseAzureStorageClustering(
            options => options.ConfigureTableServiceClient(connectionString));
    })
    .UseConsoleLifetime()
    .Build();

Suggerimento

Quando si sviluppa per Orleans, è possibile chiamare UseLocalhostClustering(ISiloBuilder, Int32, Int32, IPEndPoint, String, String) per configurare un cluster locale. Negli ambienti di produzione è consigliabile usare un provider di clustering adatto per la distribuzione.

Provider di clustering

siloBuilder.UseAzureStorageClustering(
    options => options.ConfigureTableServiceClient(connectionString))

In genere, un servizio basato su Orleans viene distribuito in un cluster di nodi, su hardware dedicato o nel cloud. Per lo sviluppo e i test di base, Orleans può essere distribuito in una configurazione a nodo singolo. Quando viene distribuito in un cluster di nodi, Orleans implementa internamente un set di protocolli per individuare e mantenere l'appartenenza dei silo Orleans nel cluster, incluso il rilevamento degli errori dei nodi e la riconfigurazione automatica.

Per una gestione affidabile dell'appartenenza al cluster, Orleans usa Tabelle di Azure, SQL Server o Apache ZooKeeper per la sincronizzazione dei nodi.

In questo esempio viene usata la tabella di Azure come provider di appartenenze.

Informazioni sul clustering Orleans

Per configurare facoltativamente il clustering, usare ClusterOptions come parametro di tipo per il metodo Configure nell'istanza di ISiloBuilder.

siloBuilder.Configure<ClusterOptions>(options =>
{
    options.ClusterId = "my-first-cluster";
    options.ServiceId = "SampleApp";
})

Qui si specificano due opzioni:

  • Impostare ClusterId su "my-first-cluster": si tratta di un ID univoco per il cluster Orleans. Tutti i client e i silo che usano questo ID potranno comunicare direttamente tra loro. È tuttavia possibile scegliere di usare un'opzione ClusterId diversa per distribuzioni diverse.
  • Impostare ServiceId su "SampleApp": si tratta di un ID univoco per l'applicazione che verrà usato da alcuni provider, ad esempio provider di persistenza. Questo ID deve rimanere stabile e non cambiare tra le distribuzioni.

Per impostazione predefinita, Orleans userà un valore di "default" sia per ServiceId che per ClusterId. Questi valori non devono essere modificati nella maggior parte dei casi. ServiceId è il più significativo dei due e viene usato per distinguere i diversi servizi logici l'uno dall'altro in modo che possano condividere sistemi di archiviazione back-end senza interferire tra loro. ClusterId viene usato per determinare quali host si connetteranno tra loro e formeranno un cluster.

All'interno di ogni cluster, tutti gli host devono usare lo stesso ServiceId. Più cluster possono tuttavia condividere un oggetto ServiceId. Ciò consente scenari di distribuzione blu/verde in cui viene avviata una nuova distribuzione (cluster) prima dell'arresto di un’altra. Questo è tipico per i sistemi ospitati nel servizio app di Azure.

Il caso più comune è che ServiceId e ClusterId rimangono fissi per la durata dell'applicazione e viene usata una strategia di distribuzione in sequenza. Questo è tipico per i sistemi ospitati in Kubernetes e Service Fabric.

Endpoint

Per impostazione predefinita, Orleans sarà in ascolto su tutte le interfacce sulla porta 11111 per la comunicazione da silo a silo e sulla porta 30000 per la comunicazione da client a silo. Per eseguire l'override di questo comportamento, chiamare ConfigureEndpoints(ISiloBuilder, Int32, Int32, AddressFamily, Boolean) e passare i numeri di porta da usare.

siloBuilder.ConfigureEndpoints(siloPort: 17_256, gatewayPort: 34_512)

Nel codice precedente:

  • La porta silo è impostata su 17_256.
  • La porta del gateway è impostata su 34_512.

Un silo Orleans ha due tipi tipici di configurazione dell'endpoint:

  • Gli endpoint da silo a silo vengono usati per la comunicazione tra silo nello stesso cluster.
  • Gli endpoint da client a silo (o gateway) vengono usati per la comunicazione tra client e silo nello stesso cluster.

Questo metodo deve essere sufficiente nella maggior parte dei casi, ma è possibile personalizzarlo ulteriormente se necessario. Di seguito è riportato un esempio di come usare un indirizzo IP esterno con alcuni port forwarding:

siloBuilder.Configure<EndpointOptions>(options =>
{
    // Port to use for silo-to-silo
    options.SiloPort = 11_111;
    // Port to use for the gateway
    options.GatewayPort = 30_000;
    // IP Address to advertise in the cluster
    options.AdvertisedIPAddress = IPAddress.Parse("172.16.0.42");
    // The socket used for client-to-silo will bind to this endpoint
    options.GatewayListeningEndpoint = new IPEndPoint(IPAddress.Any, 40_000);
    // The socket used by the gateway will bind to this endpoint
    options.SiloListeningEndpoint = new IPEndPoint(IPAddress.Any, 50_000);
})

Internamente, il silo sarà in ascolto su 0.0.0.0:40000 e 0.0.0.0:50000, ma il valore pubblicato nel provider di appartenenze sarà 172.16.0.42:11111 e 172.16.0.42:30000.

Un silo viene configurato a livello di codice tramite SiloHostBuilder e diverse classi di opzioni supplementari. Le classi di opzione in Orleans seguono il modello Opzioni in .NET e possono essere caricate tramite file, variabili di ambiente e qualsiasi provider di configurazione valido.

Esistono diversi aspetti chiave della configurazione del silo:

  • Informazioni sul clustering Orleans
  • Provider di clustering
  • Endpoint da usare per le comunicazioni da silo a silo e da client a silo
  • Parti dell'applicazione

Questo è un esempio di configurazione silo che definisce le informazioni sul cluster, usa il clustering di Azure e configura le parti dell'applicazione:

var silo = Host.CreateDefaultBuilder(args)
    .UseOrleans(builder =>
    {
        builder
            .UseAzureStorageClustering(
                options => options.ConnectionString = connectionString)
            .Configure<ClusterOptions>(options =>
            {
                options.ClusterId = "my-first-cluster";
                options.ServiceId = "AspNetSampleApp";
            })
            .ConfigureEndpoints(siloPort: 11111, gatewayPort: 30000)
            .ConfigureApplicationParts(
                parts => parts.AddApplicationPart(typeof(ValueGrain).Assembly).WithReferences())
    })
    .UseConsoleLifetime()
    .Build();

Scomposizione dei passaggi usati in questo esempio:

Provider di clustering

siloBuilder.UseAzureStorageClustering(
    options => options.ConnectionString = connectionString)

In genere, un servizio basato su Orleans viene distribuito in un cluster di nodi, su hardware dedicato o nel cloud. Per lo sviluppo e i test di base, Orleans può essere distribuito in una configurazione a nodo singolo. Quando viene distribuito in un cluster di nodi, Orleans implementa internamente un set di protocolli per individuare e mantenere l'appartenenza dei silo Orleans nel cluster, incluso il rilevamento degli errori dei nodi e la riconfigurazione automatica.

Per una gestione affidabile dell'appartenenza al cluster, Orleans usa Tabelle di Azure, SQL Server o Apache ZooKeeper per la sincronizzazione dei nodi.

In questo esempio si usa Tabella di Azure come provider di appartenenze.

Informazioni sul clustering Orleans

.Configure<ClusterOptions>(options =>
{
    options.ClusterId = "my-first-cluster";
    options.ServiceId = "AspNetSampleApp";
})

Di seguito vengono eseguite due operazioni:

  • Impostare ClusterId su "my-first-cluster": si tratta di un ID univoco per il cluster Orleans. Tutti i client e i silo che usano questo ID potranno comunicare direttamente tra loro. È tuttavia possibile scegliere di usare un'opzione ClusterId diversa per distribuzioni diverse.
  • Impostare ServiceId su "AspNetSampleApp": si tratta di un ID univoco per l'applicazione che verrà usato da alcuni provider, ad esempio provider di persistenza. Questo ID deve rimanere stabile e non cambiare tra le distribuzioni.

Per impostazione predefinita, Orleans userà un valore di "default" sia per ServiceId che per ClusterId. Questi valori non devono essere modificati nella maggior parte dei casi. ServiceId è il più significativo dei due e viene usato per distinguere i diversi servizi logici l'uno dall'altro in modo che possano condividere sistemi di archiviazione back-end senza interferire tra loro. ClusterId viene usato per determinare quali host si connetteranno tra loro e formeranno un cluster.

All'interno di ogni cluster, tutti gli host devono usare lo stesso ServiceId. Più cluster possono tuttavia condividere un oggetto ServiceId. Ciò consente scenari di distribuzione blu/verde in cui viene avviata una nuova distribuzione (cluster) prima dell'arresto di un’altra. Questo è tipico per i sistemi ospitati nel servizio app di Azure.

Il caso più comune è che ServiceId e ClusterId rimangono fissi per la durata dell'applicazione e viene usata una strategia di distribuzione in sequenza. Questo è tipico per i sistemi ospitati in Kubernetes e Service Fabric.

Endpoint

siloBuilder.ConfigureEndpoints(siloPort: 11111, gatewayPort: 30000)

Un silo Orleans ha due tipi tipici di configurazione dell'endpoint:

  • Endpoint da silo a silo, usato per la comunicazione tra silo nello stesso cluster
  • Endpoint da client a silo (o gateway), usati per la comunicazione tra client e silo nello stesso cluster

Nell'esempio viene usato il metodo helper .ConfigureEndpoints(siloPort: 11111, gatewayPort: 30000) che imposta la porta usata per la comunicazione da silo a silo a 11111 e la porta per il gateway su 30000. Questo metodo rileverà l'interfaccia da ascoltare.

Questo metodo deve essere sufficiente nella maggior parte dei casi, ma è possibile personalizzarlo ulteriormente se necessario. Di seguito è riportato un esempio di come usare un indirizzo IP esterno con alcuni port forwarding:

siloBuilder.Configure<EndpointOptions>(options =>
{
    // Port to use for silo-to-silo
    options.SiloPort = 11111;
    // Port to use for the gateway
    options.GatewayPort = 30000;
    // IP Address to advertise in the cluster
    options.AdvertisedIPAddress = IPAddress.Parse("172.16.0.42");
    // The socket used for client-to-silo will bind to this endpoint
    options.GatewayListeningEndpoint = new IPEndPoint(IPAddress.Any, 40000);
    // The socket used by the gateway will bind to this endpoint
    options.SiloListeningEndpoint = new IPEndPoint(IPAddress.Any, 50000);
})

Internamente, il silo sarà in ascolto su 0.0.0.0:40000 e 0.0.0.0:50000, ma il valore pubblicato nel provider di appartenenze sarà 172.16.0.42:11111 e 172.16.0.42:30000.

Parti dell'applicazione

siloBuilder.ConfigureApplicationParts(
    parts => parts.AddApplicationPart(
        typeof(ValueGrain).Assembly)
        .WithReferences())

Anche se questo passaggio non è tecnicamente necessario (se non configurato, Orleans analizzerà tutti gli assembly nella cartella corrente), gli sviluppatori sono invitati a configurare questa operazione. Questo passaggio consentirà a Orleans di caricare assembly e tipi utente. Questi assembly vengono definiti parti dell'applicazione. Tutti i grani, le interfacce granulari e i serializzatori vengono individuati usando le parti dell'applicazione.

Le parti dell'applicazione vengono configurate usando IApplicationPartManager, a cui è possibile accedere usando il metodo di estensione ConfigureApplicationParts su IClientBuilder e ISiloHostBuilder. Il metodo ConfigureApplicationParts accetta un delegato Action<IApplicationPartManager>.

I metodi di estensione seguenti in IApplicationPartManager supportano usi comuni:

Gli assembly aggiunti dai metodi precedenti possono essere integrati usando i metodi di estensione seguenti sul tipo restituito, IApplicationPartManagerWithAssemblies:

  • ApplicationPartManagerExtensions.WithReferences aggiunge tutti gli assembly a cui si fa riferimento dalle parti aggiunte. In questo modo vengono caricati immediatamente tutti gli assembly a cui si fa riferimento transitivamente. Gli errori di caricamento degli assembly vengono ignorati.
  • ApplicationPartManagerCodeGenExtensions.WithCodeGeneration genera il codice di supporto per le parti aggiunte e lo aggiunge al gestore della parte. Si noti che questo richiede l'installazione del pacchetto Microsoft.Orleans.OrleansCodeGenerator e viene comunemente definito generazione del codice di runtime.

L'individuazione dei tipi richiede che le parti dell'applicazione specificate includano attributi specifici. L'aggiunta del pacchetto di generazione del codice in fase di compilazione (Microsoft.Orleans.CodeGenerator.MSBuild o Microsoft.Orleans.OrleansCodeGenerator.Build) a ogni progetto contenente grani, interfacce granulari o serializzatori è l'approccio consigliato per garantire che questi attributi siano presenti. La generazione di codice in fase di compilazione supporta solo C#. Per F#, Visual Basic e altri linguaggi .NET, il codice può essere generato durante il tempo di configurazione tramite il metodo WithCodeGeneration descritto in precedenza. Altre informazioni sulla generazione del codice sono disponibili nella sezione corrispondente.