Microsoft Orleans Migration From 1 To 2 CSharp DotNetCore Microsoft Orleans

Apr 11th, 2018 - written by Kimserey with .

Prior 2.0.0 stable, we used to configure client and silo using ClientConfiguration and ClusterConfiguration. I was hard to understand how to configure those as many options were available. Moving forward to 2.0.0 stable, ClientConfiguration and ClusterConfiguration no longer exist! It has now been replaced by a ClientBuilder and a SiloBuilder (notice there is no cluster builder). The shift toward builders makes life easier to us to configure client and silo. Today I want to take the time to explain how the migration between beta 3 and stable can be done.

  1. Configure ClientBuilder
  2. Configure SiloBuilder

1. Configure the ClientBuilder

A client needs to connect to a cluster. The only configuration needed for the client is therefore:

  1. the id of the cluster
  2. the id of the service
  3. where to find the cluster

During beta this used to be configured in ClientConfiguration, it is now done using the ClientBuilder:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
IClusterClient client = new ClientBuilder()
  // 1. and 2. the id of the cluster and id of the service
  .Configure<ClusterOptions>(options =>
  {
      options.ClusterId = "cluster";
      options.ServiceId = "service";
  })
   // 3. where to find the cluster
  .UseAzureStorageClustering(options =>
  {
      options.ConnectionString = "storage connection string";
  })
  .ConfigureApplicationParts(x => x.AddApplicationPart(typeof(IAccount).Assembly).WithReferences())
  .ConfigureLogging(logging => logging.AddConsole())
  .Build();

Those settings allow the client to know where to find the cluster by pointing to the location membership table.

2. Configure the SiloBuilder

A silo needs more configurations. It is the runtime for the grains. If we leverage the grain storage, the streams and the reminders, we would need to configure the following:

  1. the id of the cluster and service
  2. where to find the cluster to join it
  3. the silo internal port (for silo to silo communication, inter cluster)
  4. the silo gateway port (for client communiction)
  5. the silo hostname
  6. the grain storage
  7. the stream service
  8. the reminder type and storage if needed

During beta this used to be configured in ClusterConfiguration, it is now done using the SiloBuilder:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
ISiloHost host = new SiloHostBuilder()
    // 1. the id of the cluster and service
    .Configure<ClusterOptions>(options =>
    {
        options.ClusterId = "";
        options.ServiceId = "";
    })
    // 2. where to find the cluster to join it
    .UseAzureStorageClustering(options => options.ConnectionString = "")
    // 3. and 4. and 5. the ports public/private and the hostname of the silo
    .ConfigureEndpoints(
        siloPort: 22000,
        gatewayPort: 32000,
        hostname: IPAddress.Loopback.ToString()
    )
    // 6. the grain storage
    .AddAzureBlobGrainStorage("default", options =>
    {
        options.ConnectionString = "connection";
        options.ContainerName = "grain-container";
    })
    // This store is needed as rendez point for streams for 7.
    .AddAzureBlobGrainStorage("PubSubStore", options =>
    {
        options.ConnectionString = "";
        options.ContainerName = "";
    })
    // 7. the stream service
    .AddSimpleMessageStreamProvider("default", (SimpleMessageStreamProviderOptions options) =>
    {
        options.FireAndForgetDelivery = true;
    })
    // 8. the reminder type and storage if needed
    .UseInMemoryReminderService()
    .ConfigureApplicationParts(x =>
    {
        x.AddApplicationPart(typeof(AccountGrain).Assembly).WithReferences();
    })
    .ConfigureLogging(b => b.AddConsole())
    .Build();

This will allow the silo to boot properly, join the cluster it is meant to be in, save grain state, save reminders and utilise the streams configured.

In the example we demonstrated configuration of a cluster on Azure with all storage using AzureBlobStorage and clustering using AzureTable with stream using AzureStorage queues.

This is also one of the major changes; the libraries have been split into meaningful libraries and meaningful namespaces.

  • The clustering is provided by the library Microsoft.Orleans.Clustering.xxx,
  • The storage persistence is provided by the library Microsoft.Orleans.Persistence.xxx,
  • The reminders are provided by the library Microsoft.Orleans.Reminders.xxx.

Here we are using Azure so everything was with .AzureStorage but if we were to use AWS, we could import .DynamoDB and we will have access to the extensions to use DynamoDB as clustering, backing storage for grains and reminders.

Further readings

If you are looking for a tutorial on how to get started with Orleans, have a look at my previous tutorials.

Designed, built and maintained by Kimserey Lam.