Orleans is a runtime and programming model for
building distributed systems, based on the actor model. In an actor based
programming model, actors represent multiple instances of related real-world
artifacts and interact with each other as independent single threaded entities.
In Orleans the actor is represented as a grain, that
contain state can be uniquely identified and expose logic via asynchronous
methods. These grains are isolated from one another and can only communicate
via messages. These grains are hosted on silos which houses the Orleans
runtime, that performs operations like grain instantiation and look-up. Even though
these silos can be connected over a network, to make request into a solo, you can create client
applications like an ASP.NET WebAPI which uses the GrainClient.GrainFactory to provide remote access. This also helps
to perform operations like authentication and authorization on the grain system
from the web Api. This also helps to create a service that encapsulates the Orleans
system so that clients don’t need to interact with the Orleans clients and do RPC,
instead can make use of the RESTful Api and use HTTP for communication.
If you are looking are looking for a sample tutorial
on how to create a grain server and host it locally, refer to the sample here: https://dotnet.github.io/orleans/Tutorials/Minimal-Orleans-Application.html
To get started, we have to create a .net core WebAPI
project and use this to as the client project to invoke calls to the silos. Follow
the steps below to use this API to invoke grain calls.
Adding nuget packages:
In the project.json file add the references to the
following nuget packages.
"Microsoft.Orleans.Core": "1.4.0",
"Microsoft.Orleans.OrleansCodeGenerator": "1.4.0",
"Microsoft.Orleans.OrleansCodeGenerator.Build": "1.4.0",
"Microsoft.Orleans.OrleansRuntime": "1.4.0",
Creating the client configuration:
Orleans can be used in a variety of configurations
that fit different usage scenarios, such as local single node deployment for
development and testing, cluster of servers, multi-instance Azure worker role,
etc. All of the different target scenarios are achieved by specifying
particular values in the Orleans configuration XML files. The client
configuration is used to specify the silos gateway endpoints to connect to. For
this sample I am using to connect to the local silo, so we should configure the
gateway to localhost. You can also use the Client configuration file to specify
the Trace settings etc.
In the WebAPI project create an XML file
ClientConfiguration.xml and copy the contents below
<ClientConfiguration xmlns="urn:orleans">
<Gateway Address="localhost" Port="30000"/>
<Tracing DefaultTraceLevel="Info"
TraceToConsole="true"
TraceToFile="C:\OrleansLogs\WebApiClient-{0}-{1}.log"
WriteTraces="false"/>
</ClientConfiguration>
Initializing the GrainClient:
The connection to the grain server/ silos are
established by initializing a grain client. The GrainClient.Initialize method
accepts a client configuration object that will initialize the client using the
configuration provided. In the Startup.cs file, use the code below to
initialize the GrainClient.
public void
StartSiloClient()
{
var config = ClientConfiguration.LoadFromFile("ClientConfiguration.xml");
// Attempt
to connect a few times to overcome transient failures and to give the silo
enough
// time to
start up when starting at the same time as the client (useful when deploying or
during development).
const int
initializeAttemptsBeforeFailing = 5;
var attempt =
0;
while (true)
{
try
{
GrainClient.Initialize(config);
break;
}
catch (SiloUnavailableException)
{
attempt++;
if (attempt
>= initializeAttemptsBeforeFailing)
{
throw;
}
Thread.Sleep(TimeSpan.FromSeconds(2));
}
}
}
The StartSiloClient can be invoked from the Configure
method in the Startup.cs file
The controller:
Now we have initialized the GrainClient, we can make
use of the static methods in the GrainFactory to get a reference to a grain and
start working.
[HttpGet]
public IActionResult GetAll()
{
var vm = GrainClient.GrainFactory.GetGrain<IGetAllVirtualMachine>(Guid.NewGuid());
var result =
vm.GetAll().Result;
if
(!result.Any())
{
return
NoContent();
}
return new OkObjectResult(result);
}
No comments:
Post a Comment