Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Configure a silo programmatically using the UseOrleans(IHostBuilder, Action<HostBuilderContext,ISiloBuilder>) extension method and several supplemental option classes. Option classes in Orleans follow the Options pattern in .NET and can be loaded from files, environment variables, or any other valid configuration provider.
There are several key aspects of silo configuration:
- Clustering provider
- (Optional) Orleans clustering information
- (Optional) Endpoints for silo-to-silo and client-to-silo communications
This example shows a silo configuration defining cluster information, using Azure clustering, and configuring application parts:
using IHost host = Host.CreateDefaultBuilder(args)
.UseOrleans(builder =>
{
builder.UseAzureStorageClustering(
options => options.ConfigureTableServiceClient(connectionString));
})
.UseConsoleLifetime()
.Build();
Tip
When developing for Orleans, you can call UseLocalhostClustering(ISiloBuilder, Int32, Int32, IPEndPoint, String, String) to configure a local cluster. In production environments, you should use a clustering provider that is suitable for your deployment.
Clustering provider
siloBuilder.UseAzureStorageClustering(
options => options.ConfigureTableServiceClient(connectionString))
Usually, you deploy a service built on Orleans on a cluster of nodes, either on dedicated hardware or in the cloud. For development and basic testing, you can deploy Orleans in a single-node configuration. When deployed to a cluster of nodes, Orleans internally implements protocols to discover and maintain membership of Orleans silos in the cluster, including detecting node failures and automatic reconfiguration.
For reliable cluster membership management, Orleans uses Azure Table, SQL Server, or Apache ZooKeeper for node synchronization.
In this sample, we use Azure Table as the membership provider.
Orleans clustering information
To optionally configure clustering, use ClusterOptions
as the type parameter for the Configure method on the ISiloBuilder
instance.
siloBuilder.Configure<ClusterOptions>(options =>
{
options.ClusterId = "my-first-cluster";
options.ServiceId = "SampleApp";
})
Here, you specify two options:
- Set the
ClusterId
to"my-first-cluster"
: This is a unique ID for the Orleans cluster. All clients and silos using this ID can talk directly to each other. You can choose to use a differentClusterId
for different deployments, though. - Set the
ServiceId
to"SampleApp"
: This is a unique ID for your application used by some providers, such as persistence providers. This ID should remain stable and not change across deployments.
By default, Orleans uses "default"
for both ServiceId
and ClusterId
. These values don't need changing in most cases. ServiceId
is more significant and distinguishes different logical services, allowing them to share backend storage systems without interference. ClusterId
determines which hosts connect to form a cluster.
Within each cluster, all hosts must use the same ServiceId
. However, multiple clusters can share a ServiceId
. This enables blue/green deployment scenarios where you start a new deployment (cluster) before shutting down another. This is typical for systems hosted in Azure App Service.
The more common case is that ServiceId
and ClusterId
remain fixed for the application's lifetime, and you use a rolling deployment strategy. This is typical for systems hosted in Kubernetes and Service Fabric.
Endpoints
By default, Orleans listens on all interfaces on port 11111
for silo-to-silo communication and port 30000
for client-to-silo communication. To override this behavior, call ConfigureEndpoints(ISiloBuilder, Int32, Int32, AddressFamily, Boolean) and pass in the port numbers you want to use.
siloBuilder.ConfigureEndpoints(siloPort: 17_256, gatewayPort: 34_512)
In the preceding code:
- The silo port is set to
17_256
. - The gateway port is set to
34_512
.
An Orleans silo has two typical types of endpoint configuration:
- Silo-to-silo endpoints: Used for communication between silos in the same cluster.
- Client-to-silo (or gateway) endpoints: Used for communication between clients and silos in the same cluster.
This method should suffice in most cases, but you can customize it further if needed. Here's an example of using an external IP address with 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);
})
Internally, the silo listens on 0.0.0.0:40000
and 0.0.0.0:50000
, but the value published in the membership provider is 172.16.0.42:11111
and 172.16.0.42:30000
.
Configure a silo programmatically via SiloHostBuilder and several supplemental option classes. Option classes in Orleans follow the Options pattern in .NET and can be loaded from files, environment variables, or any other valid configuration provider.
There are several key aspects of silo configuration:
- Orleans clustering information
- Clustering provider
- Endpoints for silo-to-silo and client-to-silo communications
- Application parts
This example shows a silo configuration defining cluster information, using Azure clustering, and configuring application parts:
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();
Let's break down the steps used in this sample:
Clustering provider
siloBuilder.UseAzureStorageClustering(
options => options.ConnectionString = connectionString)
Usually, you deploy a service built on Orleans on a cluster of nodes, either on dedicated hardware or in the cloud. For development and basic testing, you can deploy Orleans in a single-node configuration. When deployed to a cluster of nodes, Orleans internally implements protocols to discover and maintain membership of Orleans silos in the cluster, including detecting node failures and automatic reconfiguration.
For reliable cluster membership management, Orleans uses Azure Table, SQL Server, or Apache ZooKeeper for node synchronization.
In this sample, we use Azure Table as the membership provider.
Orleans clustering information
.Configure<ClusterOptions>(options =>
{
options.ClusterId = "my-first-cluster";
options.ServiceId = "AspNetSampleApp";
})
Here, we do two things:
- Set the
ClusterId
to"my-first-cluster"
: This is a unique ID for the Orleans cluster. All clients and silos using this ID can talk directly to each other. You can choose to use a differentClusterId
for different deployments, though. - Set the
ServiceId
to"AspNetSampleApp"
: This is a unique ID for your application used by some providers, such as persistence providers. This ID should remain stable and not change across deployments.
By default, Orleans uses "default"
for both ServiceId
and ClusterId
. These values don't need changing in most cases. ServiceId
is more significant and distinguishes different logical services, allowing them to share backend storage systems without interference. ClusterId
determines which hosts connect to form a cluster.
Within each cluster, all hosts must use the same ServiceId
. However, multiple clusters can share a ServiceId
. This enables blue/green deployment scenarios where you start a new deployment (cluster) before shutting down another. This is typical for systems hosted in Azure App Service.
The more common case is that ServiceId
and ClusterId
remain fixed for the application's lifetime, and you use a rolling deployment strategy. This is typical for systems hosted in Kubernetes and Service Fabric.
Endpoints
siloBuilder.ConfigureEndpoints(siloPort: 11111, gatewayPort: 30000)
An Orleans silo has two typical types of endpoint configuration:
- Silo-to-silo endpoints: Used for communication between silos in the same cluster.
- Client-to-silo endpoints (or gateway): Used for communication between clients and silos in the same cluster.
In the sample, we use the helper method .ConfigureEndpoints(siloPort: 11111, gatewayPort: 30000)
, which sets the port for silo-to-silo communication to 11111
and the gateway port to 30000
. This method detects which interface to listen on.
This method should suffice in most cases, but you can customize it further if needed. Here's an example of using an external IP address with 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);
})
Internally, the silo listens on 0.0.0.0:40000
and 0.0.0.0:50000
, but the value published in the membership provider is 172.16.0.42:11111
and 172.16.0.42:30000
.
Application parts
siloBuilder.ConfigureApplicationParts(
parts => parts.AddApplicationPart(
typeof(ValueGrain).Assembly)
.WithReferences())
Although this step isn't technically required (if not configured, Orleans scans all assemblies in the current folder), we encourage you to configure it. This step helps Orleans load user assemblies and types. These assemblies are referred to as Application Parts. Orleans discovers all Grains, Grain Interfaces, and Serializers using Application Parts.
Configure Application Parts using IApplicationPartManager, accessible via the ConfigureApplicationParts
extension method on IClientBuilder and ISiloHostBuilder. The ConfigureApplicationParts
method accepts a delegate, Action<IApplicationPartManager>
.
The following extension methods on IApplicationPartManager support common uses:
- ApplicationPartManagerExtensions.AddApplicationPart: Add a single assembly using this extension method.
- ApplicationPartManagerExtensions.AddFromAppDomain: Adds all assemblies currently loaded in the
AppDomain
. - ApplicationPartManagerExtensions.AddFromApplicationBaseDirectory: Loads and adds all assemblies in the current base path (see AppDomain.BaseDirectory).
Supplement assemblies added by the above methods using the following extension methods on their return type, IApplicationPartManagerWithAssemblies:
- ApplicationPartManagerExtensions.WithReferences: Adds all referenced assemblies from the added parts. This immediately loads any transitively referenced assemblies. Assembly loading errors are ignored.
- ApplicationPartManagerCodeGenExtensions.WithCodeGeneration: Generates support code for the added parts and adds it to the part manager. Note that this requires installing the
Microsoft.Orleans.OrleansCodeGenerator
package and is commonly referred to as runtime code generation.
Type discovery requires the provided Application Parts to include specific attributes. Adding the build-time code generation package (Microsoft.Orleans.CodeGenerator.MSBuild
or Microsoft.Orleans.OrleansCodeGenerator.Build
) to each project containing Grains, Grain Interfaces, or Serializers is the recommended approach to ensure these attributes are present. Build-time code generation only supports C#. For F#, Visual Basic, and other .NET languages, you can generate code during configuration time via the WithCodeGeneration method described above. Find more info regarding code generation in the corresponding section.