Introduction to Orleankka

[“part 1”]

Functional API for Orleans actor framework


Why Orleans?

Orleans is an actor framework that provides a straightforward approach to building distributed high-scale computing applications. Why do we need some other actor framework?

Because Orleans is not just an actor framework, it is unique and smart runtime.

It is hard to answer without understanding the underlying concepts of Orleans, but the main advantage is simplicity in all directions. I’ll try to explain here a few advantages:

  • Virtual actors - Orleans actors are virtual. That is, actor always exists. It is not explicitly created or destroyed, and it can never fail. Orleans will automatically instantiate actor when the first message arrives. You can live without boring/complicated stuff like supervisors which is so important concept in other actor frameworks and totally unnecessary thing here. You don’t need to manage the lifecycle of the actors, the runtime will do that for you. The location of the actor activation is transparent to the application code, which greatly simplifies programming. Orleans can automatically create multiple instances of the same stateless actor, seamlessly scaling out hot actors. Virtual actor approach significantly simplifies the programming model allowing the runtime to balance load and to recover from failures transparently.
  • Focus on IO (async/await) - I think everyone agrees that it is hard to imagine a web application without IO operations. For distributed world it’s also true, we need to query(or save) data from actors/database/API services. All this stuff rely on IO operations. Orleans framework was designed to properly support promises(Task<Result>). You can leverage a full power of .NET TPL with its rich abilities for composing asynchronous operations.
  • Cooperative multitasking - Orleans executes application turns using cooperative scheduler. That means that once started, an application turn runs to completion, without interruption. Orleans scheduler uses a small number of compute threads that it controls, usually equal to the number of CPU cores, to execute all application actor code. Orleans can efficiently run a large number of activations(tens of thousands to millions of actors) on a small number of threads. Cooperative multitasking also allows Orleans applications to run at very high CPU utilization.

Pain points of Orleans

One of the main pain points is that Orleans uses static code generation to build RPC proxies.

This is a very similar to what “good old” WCF does. At first, it sounds useful and convenient but in practice it is not. It has a big impact on the whole platform but at the same time it is not so obvious.

As an example, consider adding support for F#. That requires creating completely new code generator, which means a lot of work.

Creating and maintaining code generation tool for each possible target language (there are over 30 languages available on .NET platform) is a burden, so only a subset of popular languages was chosen, seriously limiting the use of the framework outside of the selection.

Below, the rest of the most painful points:

  • Proper support for F#
  • Support for custom serializations
  • Complex configuration/hosting process
  • Limited flexibility and poor composition

Welcome to the world of Orleankka

Orleankka is a functional API for Orleans which fixes a number of aforementioned problems. Below, the list of features which Orleankka brings to the table:

  • Akka style API - It’s fairly convenient, straightforward and widely used API which emphasize the nature of message passing style. It’s what we wanted to get all that time from Orleans team. Basically, you can use a significant power of high order functions to build lightweight and composable logic. Well-known thing like AOP can be applied without any additional ceremony.
  • Support of F# (but it’s easy to adopt any .NET language) - It was our one of primary goals. During implementation we encountered with one big issue - it’s F# Asynchronous Workflows which was totally broken our naive vision. The problem was because Orleans uses custom TaskScheduler and F# Async<’T> type has very limited options to incorporate with TaskScheduler. It has led that we rethink this issue and decided to forget about async { } even though this is idiomatic construction for F#.
We realized that Task<’T> is what we should follow, because it’s already standard abstraction in the whole .NET world.

We have found the good implementation of task {} computation workflow in FSharpx project and cloned it. Thank you, FSharpx ninjas!

  • Support for custom serialization - You can inject your lovely serialization format without any problems.
  • Simple configuration/hosting process - We developed a simple DSL to easily configure your environment. In addition, you can easily extend it outside of Orleankka, thanks to extension methods.

Getting started with Orleankka

OK, now it’s time to play with this magic stuff. So let’s start with the canonical Hello World.

Set up your project:
Start Visual Studio and create a new F# Console Application. Once we have our console application, we need to open up the Package Manager Console and type:

PM> Install-Package Orleankka.Fsharp

Then we need to open the relevant namespaces/modules:

Define your first actor:
First, we need to define a message to which our actor will respond to:

Once we have the message type, we can define our Actor:

Now it’s time to consume our actor, we do so by getting a proxy reference ActorSystem and calling ActorOf:


Summary

Orleankka is a breath of fresh air for anyone who is looking for more functional style API and all goodies which Orleans brings to the table. If you are interested in Orleans and like to use it - welcome to contribute!

In Part II we are going to cover very interesting aspect: error handling and reply to a sender.

We are waiting for your feedback!