Software Development

Microsoft Orleans

This image has an empty alt attribute; its file name is Orleans.png

Before We understand Orleans We need to take a look at normal Scalable Applications. Below is the Diagram that shows it

Scalability refers to an application’s capacity or ability to grow with demand without degrading performance or disrupting the user experience. When you have a scalable application, you can add more resources when needed, which improves your ability to serve customer requests under heavy load, as well as reduce downtime due to server crashes.

Problem in above Diagram

In Microsoft We have services which end up being very large and they often need some kind of way to coordinate with each other without putting too much pressure on lets say a database and without having lot of concurrency issues. Statelessness is required for scaling. Database also adds latency

Statelessness means that every HTTP request happens in complete isolation. When the client makes an HTTP request, it includes all information necessary for the server to fulfill that request. The server never relies on information from previous requests.

As Orleans are based on Actor Model.  but unlike actors in more traditional actor systems (Erlang, Akka), Orleans grains are virtual actors. The biggest difference is that physical instantiations of grains are completely abstracted away and are automatically managed by the Orleans runtime.

Small glimpse of Actor Model


A programming model for distributed systems and parallel processing
, wherein the “actor” is the primary element of computation similar to an “object” in object-oriented programming (OOP). An actor receives a message and generates output as a self-contained concurrent operation.

Actor Model Glance
Actor Life Cycle

What is Orleans

Orleans is a .NET Core, cross-platform framework for building robust, scalable distributed applications. It was created by Microsoft Research and is based on an actor model which provides an innovative approach to simplify the design of highly performant, distributed systems for the cloud. It has a programming model that solves much of the complexity associated with architecting scalable, highly-parallel, distributed systems

This is how a typical Orleans Application looks like. Orleans minimizes latency problems as well my maintaining its own state. So Database calls are not required every time rather once time

Basic Architecture of Orleans Application

Main Features

  • Framework of distributed applications
  • Build and operate scalable, fault tolerant applications that are composed of distributed objects, called grains
  • Model Your application using grains
  • Objects have id, behavior and state
  • Build on Dot net
Inside Orleans

Terms associated with Orleans

  • Grains — The “virtual actors” and/or “primitives” that are described in the actor model definition above. Grains are the objects that actually contain your logic that is to be distributed. Each individual grain is guaranteed to function in a single-threaded execution model as to greatly simplify the programming, and avoid race conditions. The grains are written in an asynchronous manner, and are intended for very fast running operations .
  • Silos — The area where your “grains” are kept. A silo can contain many grain types, as well as many instantiations of those types.
  • Clusters — A collection of silos. This allows for the “scale out” portion of Orleans. If more or less resources are needed, you can simply register or kill silos on your cluster. Scaling made easy!

More About Grain

A grain is composed of a stable identity, behavior, and state
Grain Explained

Grains are the key primitives of the Orleans programming model. Grains are the building blocks of an Orleans application, they are microscopic units of isolation, distribution, and persistence. Grains are objects that represent application entities. Just like in the Object Oriented Programming, a grain encapsulates state of an entity and encodes its behaviour in the code logic. Grains can hold references to each other and interact by invoking each other’s methods exposed via interfaces.

Orleans goal is to greatly simplify building a scalable application and eliminate most of the concurrency challenges

  • By not sharing data between grains instances except via message passing.
  • By providing the single-threaded execution guarantee to each individual grain.

A typical grain encapsulates state and behavior of a single entity (for example a specific user or a device or a session).

Grain Identity

An individual grain is a uniquely addressable instance of a grain type (class). Each grain has a unique identity, also referred to as a grain key, within its type. Grain identity within its type can be long integer, GUID, string, or combination of a long+string or GUID+string.

Accessing a Grain

A grain class implements one or more grain interfaces, formal code contracts for interacting with grains of that type. To invoke a grain, a caller needs to know the grain interface that the grain class implements that includes the method that the caller wants to call and the unique identity (key) of the target grain. For example, here’s how a user profile grain can be called to update user’s address if email is used as a user identity.

var user = grainFactory.GetGrain<IUserProfile>(userEmail);
await user.UpdateAddress(newAddress);

A call to GetGrain is an inexpensive local operation of constructing a grain reference with an embedded identity and type of the target grain.

Creating Orlean Application

An Orleans application consists of a few separate pieces, generally all as separate projects:

  • Grain interfaces
  • Grain implementations
  • Orleans Silo host
  • Orleans Client

GrainInterfaces / Grains csproj

Microsoft.Orleans.Core.Abstractions
Microsoft.Orleans.OrleansCodeGenerator.Build

Client csproj

Microsoft.Extensions.Logging.Console
Microsoft.Orleans.Client

Server csproj

Microsoft.Extensions.Logging.Console
Microsoft.Orleans.Server

Grain State and Persistence

The “Orleans” runtime provides a build in support for persistence of the state of a grain (actor). That means, developer can define a part of the grain to be persistable.
This is very important, because internally “Orleans” does not offer common object oriented command “new”, which can be used to create the grain.

Goals

  • Allow different grain types to use different types of storage providers (e.g., one uses Azure table, and one uses an ADO.NET one) or the same type of storage provider but with different configurations (e.g., both use Azure table, but one uses storage account #1 and one uses storage account #2)
  • Allow configuration of a storage provider instance to be swapped (e.g., Dev-Test-Prod) with just config file changes, and no code changes required.
  • Provide a framework to allow additional storage providers to be written later, either by the Orleans team or others.
  • Provide a minimal set of production-grade storage providers
  • Storage providers have complete control over how they store grain state data in persistent backing store.
[StorageProvider(ProviderName="store1")]
public class MyGrain<MyGrainState> ...
{
  ...
}

<OrleansConfiguration xmlns="urn:orleans">
    <Globals>
    <StorageProviders>
        <Provider Type="Orleans.Storage.MemoryStorage" Name="DevStore" />
        <Provider Type="Orleans.Storage.AzureTableStorage" Name="store1"
            DataConnectionString="DefaultEndpointsProtocol=https;AccountName=data1;AccountKey=SOMETHING1" />
        <Provider Type="Orleans.Storage.AzureBlobStorage" Name="store2"
            DataConnectionString="DefaultEndpointsProtocol=https;AccountName=data2;AccountKey=SOMETHING2"  />
    </StorageProviders>

For more information : https://github.com/L-n-G-Consultancy/orleans-sample-code

Leave a Reply