Typowe konfiguracje

Poniżej przedstawiono przykłady typowych konfiguracji, których można użyć na potrzeby wdrożeń programistycznych i produkcyjnych.

.NET Aspire jest zalecanym podejściem do konfigurowania aplikacji Orleans. Aspire Zapewnia deklaratywne zarządzanie zasobami, automatyczne odnajdywanie usług, wbudowaną możliwość obserwacji i uproszczone wdrażanie — eliminując większość konfiguracji ręcznej.

Konfiguracja produkcyjna z usługą Redis

Ta konfiguracja używa usługi Redis do klastrowania, magazynu ziarna i przypomnień z wieloma replikami silosu:

Projekt AppHost (Program.cs):

var builder = DistributedApplication.CreateBuilder(args);

var redis = builder.AddRedis("redis");

var orleans = builder.AddOrleans("cluster")
    .WithClustering(redis)
    .WithGrainStorage("Default", redis)
    .WithReminders(redis);

// Add Orleans silo with 3 replicas for production
builder.AddProject<Projects.MySilo>("silo")
    .WithReference(orleans)
    .WithReference(redis)
    .WithReplicas(3);

// Add a separate client project (e.g., an API)
builder.AddProject<Projects.MyApi>("api")
    .WithReference(orleans.AsClient())
    .WithReference(redis);

builder.Build().Run();

Projekt silosu (Program.cs):

var builder = Host.CreateApplicationBuilder(args);

builder.AddServiceDefaults();
builder.AddKeyedRedisClient("redis");
builder.UseOrleans();

builder.Build().Run();

Projekt klienta (Program.cs):

var builder = WebApplication.CreateBuilder(args);

builder.AddServiceDefaults();
builder.AddKeyedRedisClient("redis");
builder.UseOrleansClient();

var app = builder.Build();
// ... configure API endpoints
app.Run();

Wskazówka

Użyj WithReplicas(n) polecenia , aby uruchomić wiele wystąpień silosu w celu zapewnienia wysokiej dostępności. Użyj orleans.AsClient() polecenia , gdy projekt musi wywoływać tylko ziarna, a nie hostować je.

Konfiguracja produkcyjna w usłudze Azure Storage

Ta konfiguracja używa usługi Azure Table Storage do klastrowania i usługi Azure Blob Storage na potrzeby magazynu ziarna:

Projekt AppHost (Program.cs):

var builder = DistributedApplication.CreateBuilder(args);

var storage = builder.AddAzureStorage("storage")
    .RunAsEmulator();  // Use Azurite for local development
var tables = storage.AddTables("clustering");
var blobs = storage.AddBlobs("grainstate");

var orleans = builder.AddOrleans("cluster")
    .WithClustering(tables)
    .WithGrainStorage("Default", blobs);

builder.AddProject<Projects.MySilo>("silo")
    .WithReference(orleans)
    .WaitFor(storage)
    .WithReplicas(3);

builder.Build().Run();

Projekt silosu (Program.cs):

var builder = Host.CreateApplicationBuilder(args);

builder.AddServiceDefaults();
builder.AddKeyedAzureTableServiceClient("clustering");
builder.AddKeyedAzureBlobServiceClient("grainstate");
builder.UseOrleans();

builder.Build().Run();

Wskazówka

Aby użyć emulatora Azurite do programowania lokalnego, wywołaj .RunAsEmulator() zasób usługi Azure Storage, jak pokazano powyżej. Bez tego wywołania Aspire oczekuje rzeczywistego połączenia Azure Storage. W przypadku wdrożeń produkcyjnych usuń .RunAsEmulator() i skonfiguruj połączenie konta usługi Azure Storage.

Ważne

Należy wywołać odpowiednią AddKeyed* metodę (taką jak AddKeyedRedisClient, AddKeyedAzureTableServiceClientlub AddKeyedAzureBlobServiceClient), aby zarejestrować zasób zapasowy w kontenerze wstrzykiwania zależności. Orleans dostawcy wyszukują zasoby według nazwy usługi klucza — jeśli pominiesz ten krok, Orleans nie będzie można rozpoznać zasobu i zgłosi błąd rozwiązywania zależności w czasie wykonywania.

Aby uzyskać kompleksową dokumentację dotyczącą integracji Orleans i .NET Aspire, zobacz Orleans i .NET Aspire integration.

Rozwój lokalny

Aby uzyskać więcej informacji, zobacz Konfiguracja programowania lokalnego.

Tradycyjne konfiguracje (bez Aspire)

W poniższych sekcjach opisano tradycyjne konfiguracje Orleans, które nie używają .NET Aspire. Są one przydatne, gdy Aspire nie są dostępne lub gdy potrzebujesz szczegółowej kontroli nad konfiguracją Orleans .

Niezawodne wdrażanie produkcyjne przy użyciu platformy Azure

Aby uzyskać niezawodne wdrożenie produkcyjne przy użyciu platformy Azure, użyj opcji Tabela platformy Azure dla członkostwa w klastrze. Ta konfiguracja jest typowa dla wdrożeń na serwerach lokalnych, kontenerach lub wystąpieniach maszyn wirtualnych platformy Azure.

Użycie identyfikatora TokenCredential URI usługi jest zalecanym podejściem. Ten wzorzec pozwala uniknąć przechowywania wpisów tajnych w konfiguracji i używa identyfikatora Entra firmy Microsoft do bezpiecznego uwierzytelniania.

DefaultAzureCredential Zapewnia łańcuch poświadczeń, który bezproblemowo działa w lokalnych środowiskach deweloperskich i produkcyjnych. Podczas programowania używa ona poświadczeń interfejsu wiersza polecenia platformy Azure lub programu Visual Studio. W środowisku produkcyjnym na platformie Azure automatycznie używa tożsamości zarządzanej przypisanej do zasobu.

Wskazówka

DefaultAzureCredential bezproblemowo działa w ramach lokalnego programowania i produkcji. W programowania używa poświadczeń interfejsu wiersza polecenia platformy Azure lub programu Visual Studio. W środowisku produkcyjnym na platformie Azure automatycznie używa tożsamości zarządzanej zasobu. Aby uzyskać lepszą wydajność i możliwość debugowania w środowisku produkcyjnym, rozważ zastąpienie go określonym poświadczeniem, na przykład ManagedIdentityCredential. Aby uzyskać więcej informacji, zobacz Wskazówki dotyczące użycia dla elementu DefaultAzureCredential.

Konfiguracja silosu:

using Azure.Identity;

var builder = Host.CreateApplicationBuilder(args);
builder.UseOrleans(siloBuilder =>
{
    siloBuilder.Configure<ClusterOptions>(options =>
    {
        options.ClusterId = "Cluster42";
        options.ServiceId = "MyAwesomeService";
    })
    .UseAzureStorageClustering(options =>
    {
        options.ConfigureTableServiceClient(
            new Uri("https://<your-storage-account>.table.core.windows.net"),
            new DefaultAzureCredential());
    })
    .ConfigureEndpoints(siloPort: 11_111, gatewayPort: 30_000);
});

builder.Logging.SetMinimumLevel(LogLevel.Information).AddConsole();

using var host = builder.Build();

Konfiguracja klienta:

using Azure.Identity;

var builder = Host.CreateApplicationBuilder(args);
builder.UseOrleansClient(clientBuilder =>
{
    clientBuilder.Configure<ClusterOptions>(options =>
    {
        options.ClusterId = "Cluster42";
        options.ServiceId = "MyAwesomeService";
    })
    .UseAzureStorageClustering(options =>
    {
        options.ConfigureTableServiceClient(
            new Uri("https://<your-storage-account>.table.core.windows.net"),
            new DefaultAzureCredential());
    });
});

using var host = builder.Build();

Niezawodne wdrażanie produkcyjne przy użyciu platformy Azure

Aby uzyskać niezawodne wdrożenie produkcyjne przy użyciu platformy Azure, użyj opcji Tabela platformy Azure dla członkostwa w klastrze. Ta konfiguracja jest typowa dla wdrożeń na serwerach lokalnych, kontenerach lub wystąpieniach maszyn wirtualnych platformy Azure.

Format DataConnection ciągu jest rozdzieloną średnikami listą Key=Value par. Obsługiwane są następujące opcje:

Klawisz Wartość
DefaultEndpointsProtocol https
AccountName <Azure storage account>
AccountKey <Azure table storage account key>

Poniżej przedstawiono przykład DataConnection ciągu dla usługi Azure Table Storage:

"DefaultEndpointsProtocol=https;AccountName=<Azure storage account>;AccountKey=<Azure table storage account key>"

Konfiguracja silosu:

const string connectionString = "YOUR_CONNECTION_STRING_HERE";
var silo = new SiloHostBuilder()
    .Configure<ClusterOptions>(options =>
    {
        options.ClusterId = "Cluster42";
        options.ServiceId = "MyAwesomeService";
    })
    .UseAzureStorageClustering(
        options => options.ConnectionString = connectionString)
    .ConfigureEndpoints(siloPort: 11_111, gatewayPort: 30_000)
    .ConfigureLogging(builder => builder.SetMinimumLevel(LogLevel.Information).AddConsole())
    .Build();

Konfiguracja klienta:

const string connectionString = "YOUR_CONNECTION_STRING_HERE";

var client = new ClientBuilder()
    .Configure<ClusterOptions>(options =>
    {
        options.ClusterId = "Cluster42";
        options.ServiceId = "MyAwesomeService";
    })
    .UseAzureStorageClustering(
        options => options.ConnectionString = connectionString)
    .Build();

Niezawodne wdrażanie produkcyjne przy użyciu programu SQL Server

W przypadku niezawodnego wdrożenia produkcyjnego przy użyciu programu SQL Server podaj parametry połączenia programu SQL Server.

Uwaga / Notatka

Orleans Począwszy od wersji 10.0, dostawcy ADO.NET wymagają Microsoft.Data.SqlClient pakietu zamiast System.Data.SqlClient. Użyj niezmiennego Microsoft.Data.SqlClient w Orleans wersji 10.0 lub nowszej.

Orleans 10.0+

const string connectionString = "YOUR_CONNECTION_STRING_HERE";

var builder = Host.CreateApplicationBuilder(args);
builder.UseOrleans(siloBuilder =>
{
    siloBuilder.Configure<ClusterOptions>(options =>
    {
        options.ClusterId = "Cluster42";
        options.ServiceId = "MyAwesomeService";
    })
    .UseAdoNetClustering(options =>
    {
        options.ConnectionString = connectionString;
        options.Invariant = "Microsoft.Data.SqlClient"; // Orleans 10.0+
    })
    .ConfigureEndpoints(siloPort: 11111, gatewayPort: 30000);
});

builder.Logging.SetMinimumLevel(LogLevel.Information).AddConsole();

using var host = builder.Build();

Orleans 7.0-9.x

const string connectionString = "YOUR_CONNECTION_STRING_HERE";

var builder = Host.CreateApplicationBuilder(args);
builder.UseOrleans(siloBuilder =>
{
    siloBuilder.Configure<ClusterOptions>(options =>
    {
        options.ClusterId = "Cluster42";
        options.ServiceId = "MyAwesomeService";
    })
    .UseAdoNetClustering(options =>
    {
        options.ConnectionString = connectionString;
        options.Invariant = "System.Data.SqlClient";
    })
    .ConfigureEndpoints(siloPort: 11111, gatewayPort: 30000);
});

builder.Logging.SetMinimumLevel(LogLevel.Information).AddConsole();

using var host = builder.Build();

Konfiguracja klienta:

const string connectionString = "YOUR_CONNECTION_STRING_HERE";

var builder = Host.CreateApplicationBuilder(args);
builder.UseOrleansClient(clientBuilder =>
{
    clientBuilder.Configure<ClusterOptions>(options =>
    {
        options.ClusterId = "Cluster42";
        options.ServiceId = "MyAwesomeService";
    })
    .UseAdoNetClustering(options =>
    {
        options.ConnectionString = connectionString;
        // Use "Microsoft.Data.SqlClient" for Orleans 10.0+
        // Use "System.Data.SqlClient" for Orleans 7.0-9.x
        options.Invariant = "Microsoft.Data.SqlClient";
    });
});

using var host = builder.Build();

Zawodne wdrożenie w klastrze dedykowanych serwerów

W przypadku testowania w klastrze dedykowanych serwerów, w których niezawodność nie jest problemem, można wykorzystać MembershipTableGrain i uniknąć zależności od tabeli platformy Azure. Wystarczy wyznaczyć jeden z węzłów jako podstawowy.

Na silosach:

var primarySiloEndpoint = new IPEndPoint(PRIMARY_SILO_IP_ADDRESS, 11_111);

var builder = Host.CreateApplicationBuilder(args);
builder.UseOrleans(siloBuilder =>
{
    siloBuilder
        .UseDevelopmentClustering(primarySiloEndpoint)
        .Configure<ClusterOptions>(options =>
        {
            options.ClusterId = "Cluster42";
            options.ServiceId = "MyAwesomeService";
        })
        .ConfigureEndpoints(siloPort: 11_111, gatewayPort: 30_000);
});
builder.Logging.AddConsole();

using var host = builder.Build();
await host.RunAsync();

Na klientach:

var gateways = new IPEndPoint[]
{
    new IPEndPoint(PRIMARY_SILO_IP_ADDRESS, 30_000),
    new IPEndPoint(OTHER_SILO__IP_ADDRESS_1, 30_000),
    // ...
    new IPEndPoint(OTHER_SILO__IP_ADDRESS_N, 30_000),
};

var builder = Host.CreateApplicationBuilder(args);
builder.UseOrleansClient(clientBuilder =>
{
    clientBuilder.UseStaticClustering(gateways)
        .Configure<ClusterOptions>(options =>
        {
            options.ClusterId = "Cluster42";
            options.ServiceId = "MyAwesomeService";
        });
});

using var host = builder.Build();
await host.StartAsync();

Niezawodne wdrażanie produkcyjne przy użyciu programu SQL Server

W przypadku niezawodnego wdrożenia produkcyjnego przy użyciu programu SQL Server podaj parametry połączenia programu SQL Server.

Konfiguracja silosu:

const string connectionString = "YOUR_CONNECTION_STRING_HERE";
var silo = new SiloHostBuilder()
    .Configure<ClusterOptions>(options =>
    {
        options.ClusterId = "Cluster42";
        options.ServiceId = "MyAwesomeService";
    })
    .UseAdoNetClustering(options =>
    {
      options.ConnectionString = connectionString;
      options.Invariant = "System.Data.SqlClient";
    })
    .ConfigureEndpoints(siloPort: 11111, gatewayPort: 30000)
    .ConfigureLogging(builder => builder.SetMinimumLevel(LogLevel.Information).AddConsole())
    .Build();

Konfiguracja klienta:

const string connectionString = "YOUR_CONNECTION_STRING_HERE";

var client = new ClientBuilder()
    .Configure<ClusterOptions>(options =>
    {
        options.ClusterId = "Cluster42";
        options.ServiceId = "MyAwesomeService";
    })
    .UseAdoNetClustering(options =>
    {
      options.ConnectionString = connectionString;
      options.Invariant = "System.Data.SqlClient";
    })
    .Build();

Zawodne wdrożenie w klastrze dedykowanych serwerów

W przypadku testowania w klastrze dedykowanych serwerów, w których niezawodność nie jest problemem, można wykorzystać MembershipTableGrain i uniknąć zależności od tabeli platformy Azure. Wystarczy wyznaczyć jeden z węzłów jako podstawowy.

Na silosach:

var primarySiloEndpoint = new IPEndPoint(PRIMARY_SILO_IP_ADDRESS, 11_111);
var silo = new SiloHostBuilder()
    .UseDevelopmentClustering(primarySiloEndpoint)
    .Configure<ClusterOptions>(options =>
    {
        options.ClusterId = "Cluster42";
        options.ServiceId = "MyAwesomeService";
    })
    .ConfigureEndpoints(siloPort: 11_111, gatewayPort: 30_000)
    .ConfigureLogging(logging => logging.AddConsole())
    .Build();

Na klientach:

var gateways = new IPEndPoint[]
{
    new IPEndPoint(PRIMARY_SILO_IP_ADDRESS, 30_000),
    new IPEndPoint(OTHER_SILO__IP_ADDRESS_1, 30_000),
    // ...
    new IPEndPoint(OTHER_SILO__IP_ADDRESS_N, 30_000),
};

var client = new ClientBuilder()
    .UseStaticClustering(gateways)
    .Configure<ClusterOptions>(options =>
    {
        options.ClusterId = "Cluster42";
        options.ServiceId = "MyAwesomeService";
    })
    .Build();