Tag Archives: Microsoft Orleans

Getting Started with Microsoft Orleans

Microsoft Orleans is an actor model implementation for the .NET platform. The main idea of an actor model is that you distribute your computation across a number of fine-grained elements (called actors, or in Orleans, grains) which communicate between each other using message passing, and can each execute only one message at a time. This altogether avoids any need for multithreading synchronisation, and promotes distribution of computation even across physical machines.

The Orleans team have gone to great lengths to develop an API that is friendly to .NET developers, and which hides much of the complexity of building distributed systems. In this article, I hope to get you up and running with Orleans in no time.

The source code for the latter part of this article is available at the Gigi Labs BitBucket repository.

The Visual Studio Extension

If you download and install the Microsoft Orleans Tools for Visual Studio extension, you’ll get a few project templates that you can use to easily create new Orleans projects:

orleans-setup-templates

This is not strictly necessary, and I will show you how to create Orleans projects without it. But it’s quite convenient to have.

The Dev/Test Host project

A really quick way to start playing with Microsoft Orleans is to create a project of type Orleans Dev/Test Host. This is one of the project types provided by the Visual Studio extension (see previous section), and it will generate a bunch of infrastructure code (Program.cs and OrleansHostWrapper.cs) that you can use as-is. In fact, just go ahead and run it:

orleans-setup-quickrun

Just give it a few seconds; Orleans will perform some initialisation tasks, and then tell you that you have a silo running. Orleans applications typically involve a client (a regular console application, Web API, etc which communicates with Orleans) and a server (known as a silo, where all the Orleans magic happens). The Orleans Dev/Test Host is simply a way of having both in the same project.

Hello World

Among the code generated with the Orleans Dev/Test Host template, you’ll find a Main() method that looks something like this:

        static void Main(string[] args)
        {
            // The Orleans silo environment is initialized in its own app domain in order to more
            // closely emulate the distributed situation, when the client and the server cannot
            // pass data via shared memory.
            AppDomain hostDomain = AppDomain.CreateDomain("OrleansHost", null, new AppDomainSetup
            {
                AppDomainInitializer = InitSilo,
                AppDomainInitializerArguments = args,
            });

            var config = ClientConfiguration.LocalhostSilo();
            GrainClient.Initialize(config);

            // TODO: once the previous call returns, the silo is up and running.
            //       This is the place your custom logic, for example calling client logic
            //       or initializing an HTTP front end for accepting incoming requests.

            Console.WriteLine("Orleans Silo is running.\nPress Enter to terminate...");
            Console.ReadLine();

            hostDomain.DoCallBack(ShutdownSilo);
        }

We can put some of our own code instead of that comment. For this, we’ll need to create an interface:

    public interface IPerson : IGrainWithStringKey
    {
        Task SayHelloAsync(string message);
    }

One important thing to note at this stage is that interfaces used by Orleans grains must always return a Task (or Task<T>), because Orleans enforces asynchrony on its actors/grains.

Another thing to note is the IGrainWithStringKey interface we’re extending. All grains have an identifier (that’s how we’re able to find them from our code); identifiers may be of type string (as in this case), Guid, long, or a special compound type.

Next, we can create a class that implements this interface:

    public class PersonGrain : Grain, IPerson
    {
        public Task SayHelloAsync(string message)
        {
            string name = this.GetPrimaryKeyString();
            Console.WriteLine($"{name} says: {message}");

            return TaskDone.Done;
        }
    }

We’re deriving our class from Orleans’ Grain type, and we’re implementing the interface we just declared. We’re getting the grain’s identifier using the GetPrimaryKeyString() method before writing out a message. The TaskDone.Done is simply a utility task that you can return from non-async methods. Similar to the Task.CompletedTask that was introduced in .NET 4.6, this is just a convenient way to avoid doing something like Task.FromResult(0) all the time.

With that done, all we need to do is replace the comment in Main() with code such as the following:

            var joe = GrainClient.GrainFactory.GetGrain<IPerson>("Joe");
            joe.SayHelloAsync("Hello!");

This gets an instance of a grain that implements IPerson, with identifier “Joe”. The grain will be created if it doesn’t already exist; Orleans abstracts out the creation and destruction of actors. Once we have an instance, we can call methods on it. They are all asynchronous, but whether you will await them depends very much on the type of application you will be writing.

orleans-setup-hello

This is already enough for you to go on experimenting with Orleans. In the next sections (which you can safely skip if you’re just starting out), I will explain how to build out a proper project structure.

Grain Class and Grain Interface projects

There are two other project types you get with the Visual Studio extension: Orleans Grain Class Collection, and Orleans Grain Interface Collection. As your project starts to grow, you should move your grain classes and interfaces out into these project types, so that your main application consists solely of client code that interacts with Orleans via the GrainClient.GrainFactory.

NuGet packages

If you don’t want to use the Visual Studio extension, you can create regular class libraries or console applications, and just add in the necessary NuGet packages. These are the projects you need to create and the NuGet packages you need to install for each:

Purpose Type NuGet package References
Client Console Application Microsoft.Orleans.Client Interfaces
Silo Console Application Microsoft.Orleans.Server Interfaces, Grains
Grains Class Library Microsoft.Orleans.Core
Microsoft.Orleans.OrleansCodeGenerator.Build
Interfaces
Interfaces Class Library Microsoft.Orleans.Core
Microsoft.Orleans.OrleansCodeGenerator.Build

While the Microsoft.Orleans.OrleansCodeGenerator.Build package is not strictly necessary, it enables code generation for grains and grain interfaces at build time, which is better than having to do it at runtime.

A More Complete Project Structure

The rest of what we need to do to make this application work (whether using the Visual Studio extension or not) is described in the Minimal Orleans Application tutorial. I’m going to adapt it so that we have separate projects for client and silo/host (which is usually the case in real applications), to use XML configuration throughout, to fit our earlier IPerson example, and to retry to connect from the client to the silo until the silo is up.

The Silo needs the following Garbage Collection configuration to go into its App.config:

<configuration>
  <runtime>
    <gcServer enabled="true"/>
    <gcConcurrent enabled="false"/>
  </runtime>
</configuration>

Add a file called OrleansConfiguration.xml to the Silo and set it to Copy always:

<?xml version="1.0" encoding="utf-8"?>
<OrleansConfiguration xmlns="urn:orleans">
  <Globals>
    <SeedNode Address="localhost" Port="11111" />
  </Globals>
  <Defaults>
    <Networking Address="localhost" Port="11111" />
    <ProxyingGateway Address="localhost" Port="30000" />
  </Defaults>
</OrleansConfiguration>

Silo configuration needs (at a minimum) two things: an endpoint for inter-silo communication (that’s the Networking element) and an endpoint that clients outside the silo can use to talk to it (ProxyingGateway). In other words, our Client needs to talk to the Silo on port 30000.

In fact, we will now add a ClientConfiguration.xml file to the Client (set this also to Copy always):

<ClientConfiguration xmlns="urn:orleans">
  <Gateway Address="localhost" Port="30000"/>
</ClientConfiguration>

The PersonGrain class we saw earlier needs to go in the Grains project, and the IPerson interface needs to go in the Interfaces project.

Our program logic will look something like this (basically adapted from the Minimal Orleans Application tutorial, but without the client code):

    class Program
    {
        static SiloHost siloHost;

        static void Main(string[] args)
        {
            Console.Title = "Silo";

            // Orleans should run in its own AppDomain, we set it up like this
            AppDomain hostDomain = AppDomain.CreateDomain("OrleansHost", null,
                new AppDomainSetup()
                {
                    AppDomainInitializer = InitSilo
                });

            Console.WriteLine("Orleans Silo is running.\nPress Enter to terminate...");
            Console.ReadLine();

            // We do a clean shutdown in the other AppDomain
            hostDomain.DoCallBack(ShutdownSilo);
        }

        static void InitSilo(string[] args)
        {
            siloHost = new SiloHost(Dns.GetHostName());
            siloHost.LoadOrleansConfig();

            siloHost.InitializeOrleansSilo();
            var startedok = siloHost.StartOrleansSilo();
            if (!startedok)
                throw new SystemException(String.Format("Failed to start Orleans silo '{0}' as a {1} node", siloHost.Name, siloHost.Type));
        }

        static void ShutdownSilo()
        {
            if (siloHost != null)
            {
                siloHost.Dispose();
                GC.SuppressFinalize(siloHost);
                siloHost = null;
            }
        }
    }

Program logic in the Client should look something like this:

        static void Main(string[] args)
        {
            Console.Title = "Client";

            var config = ClientConfiguration.LoadFromFile("ClientConfiguration.xml");

            while (true)
            {
                try
                {
                    GrainClient.Initialize(config);
                    Console.WriteLine("Connected to silo!");

                    var friend = GrainClient.GrainFactory.GetGrain<IPerson>("Joe");
                    var result = friend.SayHelloAsync("Hello!");

                    Console.ReadLine();
                    break;
                }
                catch (SiloUnavailableException)
                {
                    Console.WriteLine("Silo not available! Retrying in 3 seconds.");
                    Thread.Sleep(3000);
                }
            }
        }

Set both the Silo and Client as startup projects, and run them. The silo will take a few seconds to initialise, and the client will keep trying to reach it until it’s up:

orleans-setup-dual

Dependency Injection in Microsoft Orleans

The source code for this article is available at the Gigi Labs BitBucket repository.

Microsoft Orleans added support for dependency injection in version 1.1.0, which was released in December 2015. It is based on ASP .NET Core’s style of dependency injection.

To see how this works, let’s create an interface and a class that implements it. It is not important what they do, but we will use them as dependencies.

    public interface IWhatever
    {
    }

    public class Whatever : IWhatever
    {
    }

In order to set up our dependency injection bindings, we need a special startup class with a ConfigureServices() method with a predefined signature. In our case, it will look like this:

    public class Startup
    {
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<IWhatever, Whatever>();

            return services.BuildServiceProvider();
        }
    }

Here we are assuming that our dependency will be in singleton scope, but if you’ve used dependency injection before, you’ll know that there are other possible scopes. In fact, you’ll notice that there are different methods supporting a variety of scopes:

orleans-di-scopes

Once we have a startup class, we need to tell Orleans to use it. This can be done either in XML configuration (refer to the official documentation on Orleans DI to see how to do this) or in code as follows:

            var config = ClusterConfiguration.LocalhostPrimarySilo();
            config.UseStartupType<Startup>();

If you’re using an Orleans Dev/Test Host project type, you’ll find this cluster configuration in OrleansHostWrapper.cs. Note that dependency injection can only be done in the server (silo) and is not currently supported in the client (so you won’t find UseStartupType() on your ClientConfiguration).

Now that we have our dependency all set up, all we need is a Grain that uses it.

    public interface IHello : IGrainWithIntegerKey
    {
        Task HelloAsync();
    }

    public class HelloGrain : Grain, IHello
    {
        private IWhatever whatever;

        public HelloGrain(IWhatever whatever)
        {
            this.whatever = whatever;
        }

        public Task HelloAsync()
        {
            Console.WriteLine("Hello!");
            return TaskDone.Done;
        }
    }

In the main program, let’s create this and call it:

            var grain = GrainClient.GrainFactory.GetGrain<IHello>(0);
            grain.HelloAsync();

Now we can run the program and see that it works without problems:

orleans-di-running

We can verify that dependency injection is working by commenting out the binding configuration in the startup class. Without it, Orleans cannot activate the grain because it cannot resolve the dependency:

orleans-di-failed

Interview: Virtual Actors with Microsoft Orleans

Introduction

In recent years, the ever increasing demand for computing resources has rendered traditional single-threaded programming inadequate for most modern applications. Faced by heavy performance and scalability challenges, many developers are forced to turn to concurrent and distributed programming.

While multithreaded programming has been in use for many years, those who have used it will know that building a performant shared memory system free of race conditions can be very challenging to get right.

It is possible to avoid the complications of shared memory systems, and indeed multithreading, by using a message passing system. An actor model is a framework where processing is done by a large number of single-threaded actors, which communicate together by sending asynchronous messages.

As it turns out, Microsoft have their own actor model, and it’s called Orleans. Sergey Bykov (SB), Principal Software Development Engineer Lead at Microsoft, and project lead of the Orleans project, has very kindly agreed to answer my (DD) questions about Orleans.

Orleans Overview

DD: What is Microsoft Orleans?

SB: The home page of our docs says the following.

“Orleans is a framework that provides a straightforward approach to building distributed high-scale computing applications, without the need to learn and apply complex concurrency or other scaling patterns. It was created by Microsoft Research and designed for use in the cloud.

“Orleans has been used extensively in Microsoft Azure by several Microsoft product groups, most notably by 343 Industries as a platform for all of Halo 4 and Halo 5 cloud services, as well as by a growing number of other companies.”

SB: In other words, Orleans provides a programming model (backed by the Orleans runtime) for building distributed scalable applications almost as easily as single machine apps. The goal of the project from the beginning was to democratize cloud development by making a broad range of developers with little to no distributed systems expertise productive and successful in building scalable distributed systems in general, and cloud services in particular.

The introduction explains that Orleans is built around a distributed actor model, and the key innovation there is the notion of Virtual Actors. Detailed description is in our publication.

DD: Out of curiosity, why the name, ‘Orleans’?

SB: It was a general rule within Microsoft that codenames should be chosen from geographical names like names of cities because those aren’t trademark-able. Over time, the codename of Orleans accrued enough brand recognition that we decided to stick with it when we went open source.

DD: Tell us a little about the history of Microsoft Orleans.

SB: Orleans started in 2009 as a research project within a new Microsoft Research lab that eventually was named eXtreme Computing Group (XCG, it was later merged with MSR’s Redmond lab). The goal for the project was to try to create something that would qualitatively simplify creating software for the cloud. The two major challenges we focused on were 1) the complexity of building distributed systems that has traditionally been the domain of a relatively small population of expert developers; and 2) the pattern of major re-architectures required from nearly every successful web property as they experienced exponential growth of their user base.

We took on building a framework with a programming mode that would make mainstream single-machine developers productive in the cloud and would help build systems and services that could easily scale through several orders of magnitude of growing scale. While focusing on mainstream developers, we wanted Orleans to be as appealing to expert developers, by reducing the amount of low level ceremony they have to deal with. As we went through several early prototypes and iterations, we learned quite a bit from building first Orleans applications, and even more so when we started collaborating with internal product groups. The programming model has evolved, and we arrived to what we ended up naming the “Virtual Actor Model”.

Using Orleans

DD: How does Microsoft Orleans compare with other actor models?

SB: The Actor Model is quite old, and there are many various implementations of it. There’s a much smaller number of available Distributed Actor Model solutions. The most popular ones are Erlang/OTP and its JVM “younger sibling” Akka. Erlang and Akka organically grew from being single process actor libraries into the multi-machine scenarios by gradually adding remoting and distribution features. They brought the fault tolerance model of hierarchical supervision trees that are easy within a single process, acceptable for small-scale fixed topologies, but are difficult to manage at cloud scale, especially for developers with limited distributed systems experience.

The Virtual Actor Model of Orleans removed a lot of coordination and fault tolerance complexity from developers’ shoulders by providing an intuitive notion of actors that don’t need to be created, destroyed or looked up. The “Virtual” qualifier comes from the analogy with virtual memory. Actors in Orleans live “eternal” life, always available for a call to process, and the Orleans runtime is responsible for instantiating their physical “incarnations” in memory on an as needed basis, and for removing idle ones to free up resources. The Orleans runtime also transparently handles failures of servers by keeping track of instantiated actors and recreating them when needed on a different server in case of a failure. As a result, the developer writes much less code (we’ve received anecdotal reports of 3-5 times reduction of code, up to 10 times in some cases) and much simpler code, free from data races and complex distributed coordination logic.

The effort of Orleans to ‘democratize’ distributed programming and to raise developer productivity received an endorsement of sort from the inventor of Actor Model, Carl Hewitt. In his recent publication Actor Model of Computation for Scalable Robust Information Systems he wrote that: “Orleans is an important step in furthering a goal of the Actor Model that application programmers need not be so concerned with low-level system details.” Obviously, that made the Orleans team very proud.

DD: In Microsoft Orleans, virtual actors are also known as grains. They run within host processes called silos. Why were these names devised?

SB: Early on we had the intuition that we’d end up with a novel programming model. In hindsight, that was prescient. The “grains” term is distinct from the already overloaded term actor, where it’s hard to tell upfront if somebody is talking about single machine concurrency or about a distributed case. In the end, “grain” is a shorthand for “Orleans actor” or “virtual actor”. When we needed to name the runtime containers for grains, we naturally went down the agricultural path with “silos”. Just imagine the confusion if called them “containers”.

DD: Who is using Microsoft Orleans, and how well does it support their systems’ scalability?

SB: Orleans has been used in production inside Microsoft since 2011. It is enjoing a growing adoption outside Microsoft after we publicly released a binary preview, and then open-sourced it. We see a wide range of systems built with Orleans: online gaming, finance, collaboration solutions, fraud detection, social network analysis, and more. One of the hottest areas is IoT. There we see Orleans-based systems that manage devices like thermostats and even, I’m not joking, mousetraps. One of the fascinating projects is the green power storage facility in Hawaii. We showed some scalability numbers in our paper.

DD: Is Microsoft Orleans meant only to be used in the cloud?

SB: The advent of the cloud brought the challenges of building reliable scalable distributed systems into the spotlight. Orleans as a project focused on solving those fundamental challenges. As a result, Orleans is equally applicable in any cloud and on premises. We have customers running Orleans in AWS and some interested in GCP, but also those that use it in private datacenters and on corporate IT infrastructures. Our first target was naturally Azure, and we built providers and extensions for it first. But Orleans was designed with extensibility in mind, and it is fairly easy to make it run pretty much anywhere.

Development and Support

DD: What is the Microsoft Orleans team currently working on, and is there a roadmap for future development?

SB: Our current focus is on making Orleans run on .NET Core, support for geo-distribution, improvements to streaming, application lifecycle and the upgrade and versioning process. Even though the project moved out of Microsoft Research to the product group, we have an ongoing collaboration with Research, which gives us a healthy pipeline of new ideas and advanced prototypes. Support for geo-disribution is one example. We also have support for indexing of actors, ACID multi-actor transactions, and reactive computations at various stages of readiness. Orleans is one of the most popular Microsoft open source projects, right next to .NET Core and Roslyn. We continue to work on it and recently substantially increased our investments.

DD: What resources are available for developers building their systems upon Microsoft Orleans?

SB: We keep hearing that our documentation is very good compared to other open source projects, but we keep improving it (and samples) as people point to topics that aren’t clear or can be explained better. The community around the project is our biggest “brain trust” and the best source of support for new people. It’s an amazing group of experienced and passionate engineers around the globe that come to our GitHub repo and Gitter chat not only because they use Orleans for their projects and contribute to it, but also because they enjoy hanging out with this very welcoming and encouraging community that always tries to help, even with topics not directly related to Orleans.