Configurer le serveur
Un silo est configuré par programmation avec la méthode d’extension UseOrleans(IHostBuilder, Action<HostBuilderContext,ISiloBuilder>) et plusieurs classes d’options supplémentaires. Les classes d’options dans Orleans suivent le Modèle d’options dans .NET et peuvent être chargées via des fichiers, des variables d’environnement ou tout fournisseur de configuration valide.
La configuration des silos présente plusieurs aspects de première importance :
- Fournisseur de clustering
- (Facultatif) Informations de clustering Orleans
- (Facultatif) Points de terminaison à utiliser pour les communications de silo à silo et de client à silo
Il s’agit d’un exemple de configuration de silo qui définit les informations de cluster, utilise le clustering Azure et configure les composants d’application :
using IHost host = Host.CreateDefaultBuilder(args)
.UseOrleans(builder =>
{
builder.UseAzureStorageClustering(
options => options.ConfigureTableServiceClient(connectionString));
})
.UseConsoleLifetime()
.Build();
Conseil
Lors du développement pour Orleans, vous pouvez appeler UseLocalhostClustering(ISiloBuilder, Int32, Int32, IPEndPoint, String, String) pour configurer un cluster local. Dans les environnements de production, vous devez utiliser un fournisseur de clustering adapté à votre déploiement.
Fournisseur de clustering
siloBuilder.UseAzureStorageClustering(
options => options.ConfigureTableServiceClient(connectionString))
En règle générale, un service créé sur Orleans est déployé sur un cluster de nœuds, soit sur du matériel dédié, soit dans le cloud. Pour les tests de base et de développement, Orleans peut être déployé dans une configuration à nœud unique. Lorsqu’il est déployé dans un cluster de nœuds, Orleans implémente en interne un ensemble de protocoles pour découvrir et maintenir l’appartenance des silos Orleans dans le cluster, notamment la détection des défaillances de nœud et la reconfiguration automatique.
Pour une gestion fiable de l’appartenance au cluster, Orleans utilise Table Azure, SQL Server ou Apache ZooKeeper pour la synchronisation des nœuds.
Dans cet exemple, nous utilisons Table Azure comme fournisseur d’appartenances.
Informations de clustering Orleans
Pour configurer éventuellement le clustering, utilisez ClusterOptions
comme paramètre de type pour la méthode Configure sur l’instance ISiloBuilder
.
siloBuilder.Configure<ClusterOptions>(options =>
{
options.ClusterId = "my-first-cluster";
options.ServiceId = "SampleApp";
})
Ici vous spécifiez deux options :
- Définissez
ClusterId
sur"my-first-cluster"
: il s’agit d’un ID unique pour le cluster Orleans. Tous les clients et les silos qui utilisent cet ID peuvent communiquer directement entre eux. Toutefois, vous pouvez choisir d’utiliser un autreClusterId
pour différents déploiements. - Nous définissons
ServiceId
sur"SampleApp"
: il s’agit d’un ID unique pour votre application, qui sera utilisé par certains fournisseurs, tels que les fournisseurs de persistance. Cet ID doit rester stable et ne pas changer entre les déploiements.
Par défaut, Orleans utilise la valeur "default"
pour ServiceId
et ClusterId
. Ces valeurs n’ont pas besoin d’être modifiées dans la plupart des cas. ServiceId
est le plus important des deux, et est utilisé pour distinguer différents services logiques entre eux afin qu’ils puissent partager des systèmes de stockage backend sans interférer les uns avec les autres. ClusterId
est utilisé pour déterminer quels hôtes se connecteront entre eux et formeront un cluster.
Dans chaque cluster, tous les hôtes doivent utiliser le même ServiceId
. Toutefois, plusieurs clusters peuvent partager un ServiceId
. Cela permet des scénarios de déploiement bleu/vert où un nouveau déploiement (cluster) est démarré avant l’arrêt d’un autre. Cela est typique pour les systèmes hébergés dans Azure App Service.
Le cas le plus courant est que ServiceId
et ClusterId
restent fixes pendant la durée de vie de l’application et qu’une stratégie de déploiement propagée est utilisée. C’est typique pour les systèmes hébergés dans Kubernetes et Service Fabric.
Points de terminaison
Par défaut, Orleans écoute toutes les interfaces sur le port 11111
pour la communication de silo à silo et sur le port 30000
pour la communication de client à silo. Pour remplacer ce comportement, appelez ConfigureEndpoints(ISiloBuilder, Int32, Int32, AddressFamily, Boolean) et transmettez les numéros de port que vous souhaitez utiliser.
siloBuilder.ConfigureEndpoints(siloPort: 17_256, gatewayPort: 34_512)
Dans le code précédent :
- Le port de silo est défini sur
17_256
. - Le port de passerelle est défini sur
34_512
.
Un silo Orleans a deux types standards de configuration de point de terminaison :
- Les points de terminaison de silo à silo, utilisés pour la communication entre les silos dans le même cluster.
- Les points de terminaison de client à silo (ou passerelle), utilisés pour la communication entre les clients et les silos dans le même cluster.
Cette méthode doit être suffisante dans la plupart des cas, mais vous pouvez la personnaliser davantage si vous en avez besoin. Voici un exemple d’utilisation d’une adresse IP externe avec transfert de port :
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);
})
En interne, le silo écoute 0.0.0.0:40000
et 0.0.0.0:50000
, mais la valeur publiée dans le fournisseur d’appartenances sera 172.16.0.42:11111
et 172.16.0.42:30000
.
Un silo est configuré programmatiquement via SiloHostBuilder et plusieurs classes d’options supplémentaires. Les classes d’options dans Orleans suivent le Modèle d’options dans .NET et peuvent être chargées via des fichiers, des variables d’environnement ou tout fournisseur de configuration valide.
La configuration des silos présente plusieurs aspects de première importance :
- Informations de clustering Orleans
- Fournisseur de clustering
- Points de terminaison à utiliser pour les communications de silo à silo et de client à silo
- Composants d’application
Il s’agit d’un exemple de configuration de silo qui définit les informations de cluster, utilise le clustering Azure et configure les composants d’application :
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();
Nous allons décomposer les étapes utilisées dans cet exemple :
Fournisseur de clustering
siloBuilder.UseAzureStorageClustering(
options => options.ConnectionString = connectionString)
En règle générale, un service créé sur Orleans est déployé sur un cluster de nœuds, soit sur du matériel dédié, soit dans le cloud. Pour les tests de base et de développement, Orleans peut être déployé dans une configuration à nœud unique. Lorsqu’il est déployé dans un cluster de nœuds, Orleans implémente en interne un ensemble de protocoles pour découvrir et maintenir l’appartenance des silos Orleans dans le cluster, notamment la détection des défaillances de nœud et la reconfiguration automatique.
Pour une gestion fiable de l’appartenance au cluster, Orleans utilise Table Azure, SQL Server ou Apache ZooKeeper pour la synchronisation des nœuds.
Dans cet exemple, nous utilisons Table Azure comme fournisseur d’appartenances.
Informations de clustering Orleans
.Configure<ClusterOptions>(options =>
{
options.ClusterId = "my-first-cluster";
options.ServiceId = "AspNetSampleApp";
})
Ici, nous effectuons deux actions :
- Définissez
ClusterId
sur"my-first-cluster"
: il s’agit d’un ID unique pour le cluster Orleans. Tous les clients et les silos qui utilisent cet ID peuvent communiquer directement entre eux. Toutefois, vous pouvez choisir d’utiliser un autreClusterId
pour différents déploiements. - Nous définissons
ServiceId
sur"AspNetSampleApp"
: il s’agit d’un ID unique pour votre application, qui sera utilisé par certains fournisseurs, tels que les fournisseurs de persistance. Cet ID doit rester stable et ne pas changer entre les déploiements.
Par défaut, Orleans utilise la valeur "default"
pour ServiceId
et ClusterId
. Ces valeurs n’ont pas besoin d’être modifiées dans la plupart des cas. ServiceId
est le plus important des deux, et est utilisé pour distinguer différents services logiques entre eux afin qu’ils puissent partager des systèmes de stockage backend sans interférer les uns avec les autres. ClusterId
est utilisé pour déterminer quels hôtes se connecteront entre eux et formeront un cluster.
Dans chaque cluster, tous les hôtes doivent utiliser le même ServiceId
. Toutefois, plusieurs clusters peuvent partager un ServiceId
. Cela permet des scénarios de déploiement bleu/vert où un nouveau déploiement (cluster) est démarré avant l’arrêt d’un autre. Cela est typique pour les systèmes hébergés dans Azure App Service.
Le cas le plus courant est que ServiceId
et ClusterId
restent fixes pendant la durée de vie de l’application et qu’une stratégie de déploiement propagée est utilisée. C’est typique pour les systèmes hébergés dans Kubernetes et Service Fabric.
Points de terminaison
siloBuilder.ConfigureEndpoints(siloPort: 11111, gatewayPort: 30000)
Un silo Orleans a deux types standards de configuration de point de terminaison :
- Les points de terminaison de silo à silo, utilisés pour la communication entre les silos dans le même cluster
- Les points de terminaison de client à silo (ou passerelle), utilisés pour la communication entre les clients et les silos dans le même cluster
Dans cet exemple, nous utilisons la méthode d’assistance .ConfigureEndpoints(siloPort: 11111, gatewayPort: 30000)
qui définit le port utilisé pour la communication de silo à silo sur 11111
et le port pour la passerelle sur 30000
.
Cette méthode détecte l’interface à écouter.
Cette méthode doit être suffisante dans la plupart des cas, mais vous pouvez la personnaliser davantage si vous en avez besoin. Voici un exemple d’utilisation d’une adresse IP externe avec transfert de port :
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);
})
En interne, le silo écoute 0.0.0.0:40000
et 0.0.0.0:50000
, mais la valeur publiée dans le fournisseur d’appartenances sera 172.16.0.42:11111
et 172.16.0.42:30000
.
Composants d’application
siloBuilder.ConfigureApplicationParts(
parts => parts.AddApplicationPart(
typeof(ValueGrain).Assembly)
.WithReferences())
Bien que cette étape ne soit pas techniquement requise (si elle n’est pas configurée, Orleans analyse tous les assemblies dans le dossier actif), les développeurs sont encouragés à la configurer. Cette étape aide Orleans à charger les assemblies et les types d’utilisateur. Ces assemblys sont appelés composants d’application. Tous les grains, interfaces grain et sérialiseurs sont découverts à l’aide de composants d’application.
Les composants d’application sont configurés à l’aide de IApplicationPartManager, qui est accessible à l’aide de la méthode d’extension ConfigureApplicationParts
sur IClientBuilder et ISiloHostBuilder. La méthode ConfigureApplicationParts
accepte un délégué, Action<IApplicationPartManager>
.
Les méthodes d’extension suivantes sur IApplicationPartManager prennent en charge les utilisations courantes :
- ApplicationPartManagerExtensions.AddApplicationPart : un assembly unique peut être ajouté à l’aide de cette méthode d’extension.
- ApplicationPartManagerExtensions.AddFromAppDomain ajoute tous les assemblys actuellement chargés dans
AppDomain
. - ApplicationPartManagerExtensions.AddFromApplicationBaseDirectory charge et ajoute tous les assemblys dans le chemin de base actuel (voir AppDomain.BaseDirectory).
Les assemblys ajoutés par les méthodes ci-dessus peuvent être complétés à l’aide des méthodes d’extension suivantes sur leur type de retour, IApplicationPartManagerWithAssemblies :
- ApplicationPartManagerExtensions.WithReferences ajoute tous les assemblys référencés à partir des composants ajoutés. Cela charge immédiatement les assemblys référencés de manière transitive. Les erreurs de chargement d’assembly sont ignorées.
- ApplicationPartManagerCodeGenExtensions.WithCodeGeneration génère le code de prise en charge des composants ajoutés et l’ajoute au gestionnaire de composants. Notez que cela exige que le package
Microsoft.Orleans.OrleansCodeGenerator
soit installé et communément appelé « génération de code d’exécution ».
La détection des types exige que les composants d’application fournis incluent des attributs spécifiques. L’ajout du package de génération de code au moment de la génération (Microsoft.Orleans.CodeGenerator.MSBuild
ou Microsoft.Orleans.OrleansCodeGenerator.Build
) à chaque projet contenant des grains, des interfaces de grain ou des sérialiseurs constitue l’approche recommandée pour garantir la présence de ces attributs. La génération de code au moment de la génération prend en charge C# uniquement. Pour F#, Visual Basic et les autres langages .NET, le code peut être généré pendant la configuration via la méthode WithCodeGeneration décrite ci-dessus. Vous trouverez plus d’informations sur la génération de code dans la section correspondante.