Serverkonfiguration
Ein Silo wird programmgesteuert mit der Erweiterungsmethode UseOrleans(IHostBuilder, Action<HostBuilderContext,ISiloBuilder>) und mehreren zusätzlichen Optionsklassen konfiguriert. Optionsklassen in Orleans folgen dem Optionsmuster in .NET und können über Dateien, Umgebungsvariablen und jeden gültigen Konfigurationsanbieter geladen werden.
Es gibt mehrere wichtige Aspekte bei der Silokonfiguration:
- Clusteringanbieter
- (Optional) Orleans-Clusterinformationen
- (Optional) Endpunkte für die Kommunikation zwischen Silos und für die Kommunikation zwischen Clients und Silos
Im Anschluss sehen Sie ein Beispiel für eine Silokonfiguration, die Clusterinformationen definiert, Azure-Clustering verwendet und die Anwendungsparts konfiguriert:
using IHost host = Host.CreateDefaultBuilder(args)
.UseOrleans(builder =>
{
builder.UseAzureStorageClustering(
options => options.ConfigureTableServiceClient(connectionString));
})
.UseConsoleLifetime()
.Build();
Tipp
Bei der Entwicklung für Orleans können Sie UseLocalhostClustering(ISiloBuilder, Int32, Int32, IPEndPoint, String, String) aufrufen, um einen lokalen Cluster zu konfigurieren. In Produktionsumgebungen sollten Sie einen Clusteringanbieter verwenden, der für Ihre Bereitstellung geeignet ist.
Clusteringanbieter
siloBuilder.UseAzureStorageClustering(
options => options.ConfigureTableServiceClient(connectionString))
In der Regel wird ein auf Orleans basierender Dienst auf einem Cluster mit Knoten bereitgestellt, entweder auf dedizierter Hardware oder in der Cloud. Für die Entwicklung und grundlegende Tests kann Orleans in einer Konfiguration mit nur einem Knoten bereitgestellt werden. Bei der Bereitstellung in einem Cluster mit Knoten implementiert Orleans intern eine Reihe von Protokollen zum Ermitteln und Verwalten der Mitgliedschaft von Orleans-Silos im Cluster, einschließlich Erkennung von Knotenfehlern und automatischer Neukonfiguration.
Für die zuverlässige Verwaltung der Clustermitgliedschaft verwendet Orleans Azure Table, SQL Server oder Apache ZooKeeper für die Synchronisierung von Knoten.
In diesem Beispiel wird Azure Table als Mitgliedschaftsanbieter verwendet.
Informationen zum Orleans-Clustering
Verwenden Sie zum optionalen Konfigurieren des Clusterings ClusterOptions
als Typparameter für die Configure-Methode in der ISiloBuilder
-Instanz.
siloBuilder.Configure<ClusterOptions>(options =>
{
options.ClusterId = "my-first-cluster";
options.ServiceId = "SampleApp";
})
Hier geben Sie zwei Optionen an:
- Legen Sie
ClusterId
auf"my-first-cluster"
fest: Dies ist eine eindeutige ID für den Orleans-Cluster. Alle Clients und Silos, die diese ID verwenden, können direkt miteinander kommunizieren. Sie können jedoch eine andere Cluster-ID (ClusterId
) für verschiedene Bereitstellungen verwenden. - Legen Sie
ServiceId
auf"SampleApp"
fest: Dies ist eine eindeutige ID für Ihre Anwendung, die von einigen Anbietern (z. B. Persistenzanbietern) verwendet wird. Diese ID sollte gleich bleiben und sich nicht über Bereitstellungen hinweg ändern.
Standardmäßig verwendet Orleans den Wert "default"
für ServiceId
und ClusterId
. Diese Werte müssen in den meisten Fällen nicht geändert werden. ServiceId
ist der wichtigere der beiden Werte. Er wird verwendet, um verschiedene logische Dienste voneinander zu unterscheiden, sodass sie Back-End-Speichersysteme gemeinsam nutzen können, ohne sich gegenseitig zu beeinträchtigen. Mithilfe von ClusterId
wird ermittelt, welche Hosts eine Verbindung miteinander herstellen und einen Cluster bilden.
In den einzelnen Clustern müssen alle Hosts dieselbe Dienst-ID (ServiceId
) verwenden. Mehrere Cluster können jedoch die gleiche Dienst-ID (ServiceId
) nutzen. Dadurch werden Szenarien für Blau-Grün-Bereitstellungen ermöglicht, in denen eine neue Bereitstellung (Cluster) gestartet wird, bevor eine andere heruntergefahren wird. Dies ist typisch für Systeme, die in Azure App Service gehostet werden.
Gängiger ist, dass ServiceId
und ClusterId
während der Lebensdauer der Anwendung beibehalten werden und eine Rolling-Bereitstellungsstrategie verwendet wird. Dies ist typisch für Systeme, die in Kubernetes und Service Fabric gehostet werden.
Endpunkte
Orleans überwacht standardmäßig alle Schnittstellen am Port 11111
für die Kommunikation zwischen Silos und am Port 30000
für die Kommunikation zwischen Clients und Silos. Um dieses Verhalten zu überschreiben, rufen Sie ConfigureEndpoints(ISiloBuilder, Int32, Int32, AddressFamily, Boolean) auf, und übergeben Sie die zu verwendenden Portnummern.
siloBuilder.ConfigureEndpoints(siloPort: 17_256, gatewayPort: 34_512)
Für den Code oben gilt:
- Der Siloport ist auf
17_256
festgelegt. - Der Gatewayport ist auf
34_512
festgelegt.
Ein Orleans-Silo weist zwei typische Arten von Endpunktkonfigurationen auf:
- Silo-zu-Silo-Endpunkte werden für die Kommunikation zwischen Silos im selben Cluster verwendet.
- Client-zu-Silo-Endpunkte (oder Gatewayendpunkte) werden für die Kommunikation zwischen Clients und Silos im selben Cluster verwendet.
Diese Methode sollte in den meisten Fällen ausreichend sein, Sie können sie jedoch bei Bedarf weiter anpassen. Hier sehen Sie ein Beispiel für die Verwendung einer externen IP-Adresse mit einer Portweiterleitung:
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);
})
Intern lauscht das Silo an 0.0.0.0:40000
und 0.0.0.0:50000
, aber die im Mitgliedschaftsanbieter veröffentlichten Werte lauten 172.16.0.42:11111
und 172.16.0.42:30000
.
Ein Silo wird programmgesteuert über SiloHostBuilder und mehrere zusätzliche Optionsklassen konfiguriert. Optionsklassen in Orleans folgen dem Optionsmuster in .NET und können über Dateien, Umgebungsvariablen und jeden gültigen Konfigurationsanbieter geladen werden.
Es gibt mehrere wichtige Aspekte bei der Silokonfiguration:
- Informationen zum Orleans-Clustering
- Clusteringanbieter
- Endpunkte für die Kommunikation zwischen Silos und für die Kommunikation zwischen Clients und Silos
- Teile der Anwendung
Im Anschluss sehen Sie ein Beispiel für eine Silokonfiguration, die Clusterinformationen definiert, Azure-Clustering verwendet und die Anwendungsparts konfiguriert:
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();
Sehen Sie sich die in diesem Beispiel verwendeten Schritte genauer an:
Clusteringanbieter
siloBuilder.UseAzureStorageClustering(
options => options.ConnectionString = connectionString)
In der Regel wird ein auf Orleans basierender Dienst auf einem Cluster mit Knoten bereitgestellt, entweder auf dedizierter Hardware oder in der Cloud. Für die Entwicklung und grundlegende Tests kann Orleans in einer Konfiguration mit nur einem Knoten bereitgestellt werden. Bei der Bereitstellung in einem Cluster mit Knoten implementiert Orleans intern eine Reihe von Protokollen zum Ermitteln und Verwalten der Mitgliedschaft von Orleans-Silos im Cluster, einschließlich Erkennung von Knotenfehlern und automatischer Neukonfiguration.
Für die zuverlässige Verwaltung der Clustermitgliedschaft verwendet Orleans Azure Table, SQL Server oder Apache ZooKeeper für die Synchronisierung von Knoten.
In diesem Beispiel wird Azure Table als Mitgliedschaftsanbieter verwendet.
Informationen zum Orleans-Clustering
.Configure<ClusterOptions>(options =>
{
options.ClusterId = "my-first-cluster";
options.ServiceId = "AspNetSampleApp";
})
Hier führen Sie zwei Schritte aus:
- Legen Sie
ClusterId
auf"my-first-cluster"
fest: Dies ist eine eindeutige ID für den Orleans-Cluster. Alle Clients und Silos, die diese ID verwenden, können direkt miteinander kommunizieren. Sie können jedoch eine andere Cluster-ID (ClusterId
) für verschiedene Bereitstellungen verwenden. - Legen Sie
ServiceId
auf"AspNetSampleApp"
fest: Dies ist eine eindeutige ID für Ihre Anwendung, die von einigen Anbietern (z. B. Persistenzanbietern) verwendet wird. Diese ID sollte gleich bleiben und sich nicht über Bereitstellungen hinweg ändern.
Standardmäßig verwendet Orleans den Wert "default"
für ServiceId
und ClusterId
. Diese Werte müssen in den meisten Fällen nicht geändert werden. ServiceId
ist der wichtigere der beiden Werte. Er wird verwendet, um verschiedene logische Dienste voneinander zu unterscheiden, sodass sie Back-End-Speichersysteme gemeinsam nutzen können, ohne sich gegenseitig zu beeinträchtigen. Mithilfe von ClusterId
wird ermittelt, welche Hosts eine Verbindung miteinander herstellen und einen Cluster bilden.
In den einzelnen Clustern müssen alle Hosts dieselbe Dienst-ID (ServiceId
) verwenden. Mehrere Cluster können jedoch die gleiche Dienst-ID (ServiceId
) nutzen. Dadurch werden Szenarien für Blau-Grün-Bereitstellungen ermöglicht, in denen eine neue Bereitstellung (Cluster) gestartet wird, bevor eine andere heruntergefahren wird. Dies ist typisch für Systeme, die in Azure App Service gehostet werden.
Gängiger ist, dass ServiceId
und ClusterId
während der Lebensdauer der Anwendung beibehalten werden und eine Rolling-Bereitstellungsstrategie verwendet wird. Dies ist typisch für Systeme, die in Kubernetes und Service Fabric gehostet werden.
Endpunkte
siloBuilder.ConfigureEndpoints(siloPort: 11111, gatewayPort: 30000)
Ein Orleans-Silo weist zwei typische Arten von Endpunktkonfigurationen auf:
- Silo-zu-Silo-Endpunkte. Diese werden für die Kommunikation zwischen Silos im selben Cluster verwendet.
- Client-zu-Silo-Endpunkte (oder Gatewayendpunkte). Diese werden für die Kommunikation zwischen Clients und Silos im selben Cluster verwendet.
Im Beispiel verwenden Sie die Hilfsmethode .ConfigureEndpoints(siloPort: 11111, gatewayPort: 30000)
, die den für die Kommunikation zwischen Silos verwendeten Port auf 11111
und den Port für das Gateway auf 30000
festlegt.
Diese Methode erkennt, auf welche Schnittstelle gelauscht werden soll.
Diese Methode sollte in den meisten Fällen ausreichend sein, Sie können sie jedoch bei Bedarf weiter anpassen. Hier sehen Sie ein Beispiel für die Verwendung einer externen IP-Adresse mit einer Portweiterleitung:
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);
})
Intern lauscht das Silo an 0.0.0.0:40000
und 0.0.0.0:50000
, aber die im Mitgliedschaftsanbieter veröffentlichten Werte lauten 172.16.0.42:11111
und 172.16.0.42:30000
.
Teile der Anwendung
siloBuilder.ConfigureApplicationParts(
parts => parts.AddApplicationPart(
typeof(ValueGrain).Assembly)
.WithReferences())
Obwohl dieser Schritt technisch nicht erforderlich ist, wird Entwicklern empfohlen, ihn zu konfigurieren. (Wenn er nicht konfiguriert wird, überprüft Orleans alle Assemblys im aktuellen Ordner.) Dieser Schritt hilft Orleans beim Laden von Benutzerassemblys und -typen. Diese Assemblys werden als Anwendungsparts bezeichnet. Alle Grains, Grainschnittstellen und Serialisierungsmodule werden mithilfe von Anwendungsparts ermittelt.
Anwendungsparts werden mithilfe von IApplicationPartManager konfiguriert. Darauf kann mithilfe der ConfigureApplicationParts
-Erweiterungsmethode für IClientBuilder und ISiloHostBuilder zugegriffen werden kann. Die ConfigureApplicationParts
-Methode akzeptiert den Delegaten Action<IApplicationPartManager>
.
Die folgenden Erweiterungsmethoden für IApplicationPartManager unterstützen gängige Anwendungsfälle:
- ApplicationPartManagerExtensions.AddApplicationPart: Mit dieser Erweiterungsmethode kann eine einzelne Assembly hinzugefügt werden.
- ApplicationPartManagerExtensions.AddFromAppDomain fügt alle Assemblys hinzu, die derzeit in
AppDomain
geladen sind. - ApplicationPartManagerExtensions.AddFromApplicationBaseDirectory lädt alle Assemblys im aktuellen Basispfad und fügt sie hinzu (siehe AppDomain.BaseDirectory).
Assemblys, die von den oben genannten Methoden hinzugefügt werden, können mithilfe der folgenden Erweiterungsmethoden für ihren Rückgabetyp ergänzt werden (IApplicationPartManagerWithAssemblies):
- ApplicationPartManagerExtensions.WithReferences fügt alle Assemblys, auf die verwiesen wird, aus den hinzugefügten Parts hinzu. Dadurch werden sofort alle Assemblys geladen, auf die transitiv verwiesen wird. Fehler beim Laden von Assemblys werden ignoriert.
- ApplicationPartManagerCodeGenExtensions.WithCodeGeneration generiert Unterstützungscode für die hinzugefügten Parts und fügt ihn dem Part-Manager hinzu. Beachten Sie, dass hierfür das Paket
Microsoft.Orleans.OrleansCodeGenerator
installiert werden muss und der Vorgang häufig als Codegenerierung während der Laufzeit bezeichnet wird.
Die Typermittlung erfordert, dass die bereitgestellten Anwendungsparts bestimmte Attribute enthalten. Das Hinzufügen des Pakets für die Codegenerierung zur Buildzeit (Microsoft.Orleans.CodeGenerator.MSBuild
oder Microsoft.Orleans.OrleansCodeGenerator.Build
) zu jedem Projekt, das Grains, Grainschnittstellen oder Serialisierungsmodule enthält, ist der empfohlene Ansatz, um sicherzustellen, dass diese Attribute vorhanden sind. Die Codegenerierung zur Buildzeit unterstützt nur C#. Für F#, Visual Basic und andere .NET-Sprachen kann Code während der Konfiguration über die oben beschriebene WithCodeGeneration-Methode generiert werden. Weitere Informationen zur Codegenerierung finden Sie im entsprechenden Abschnitt.