Michele
Posted on February 22, 2023
I'm not going to spend time to introduce the Microsoft Orleans framework here, as the MSDN documentation does a pretty good job at that.
The building blocks of an application using Orleans are
- The silo
- The client
- The grains interfaces
- The grains implementations
In a production environment these blocks usually live in separate projects, but we don't need to do that to start the simplest possible silo.
Step one
Create a new web application. This will host the silo and also act as the client.
dotnet new web -o GettingStartedOrleans
Step two
Inside the GettingStartedOrleans folder, the program.cs file should look like this
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Orleans 7 provides three main nuget packages:
- Microsoft.Orleans.Server
- Microsoft.Orleans.Client
- Microsoft.Orleans.Sdk
When building a silo, we only need to reference Server, which in turn will reference Client and Sdk. This means that on a silo, we always have a client available.
When building an application that connects to an Orleans silo, we only need to reference Client.
Finally, when building other libraries that contain Orleans related code (e.g. Grains and Grain Interfaces), we should just reference SDK.
In our case, we'll add Microsoft.Orleans.Server to our project
dotnet add package Microsoft.Orleans.Server
Step three
Open the program.cs file and add this line
builder.Host.UseOrleans(silobuilder=>silobuilder.UseLocalhostClustering());
before
var app = builder.Build();
If we run the application now, we'll have a web application and an Orleans silo running side by side, with the web application already connected to the silo.
The Orleans SDK automatically registers an instance of IClientService and connects to the Orleans silo, so that when we write our code, all we will need to do is to inject the IClientService and use.
Step four
At this point we can create our first grain. To do that we first write the grain interface:
public interface IPingGrain : IGrainWithGuidKey
{
ValueTask<string> Pong(string name);
}
Our Ping grain interface inherits from IGrainWithGuidKey. The Guid will be used to identify a unique grain.
The implementation will look like this:
public sealed class PingGrain : IPingGrain
{
public ValueTask<string> Pong(string name) => ValueTask.FromResult(name);
}
Step five
All is left now is to call the grain from our api.
We can modify the existing route with something like:
app.MapGet("/hello/{name}", async (string name, IClusterClient clusterClient) =>
await clusterClient.GetGrain<IPingGrain>(Guid.NewGuid()).Pong(name));
Notice how we:
- anject IClusterClient in the api call. It's been automatically registered and initialized by the framework
- simply await the Pong method from the IPingGrain interface.
Conclusions
We can start the project with a simple
dotnet run
Calling our Api with (change the port if different)
curl http://localhost:5000/hello/michele
will return
michele
This sample demonstrates how quickly we can start a web application and an Orleans silo in a development environment. This will allow us to quickly experiment with the framework and understand the fundamental building blocks.
In the next post we'll introduce request and response objects, which will bring us in the magic world of serialization!
Photo by Alina Grubnyak on Unsplash
Posted on February 22, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.