Busy .NET Developer's Guide to Orleans

ted.neward@newardassociates.com | Blog: http://blogs.newardassociates.com | Github: tedneward | LinkedIn: tedneward

Objectives

Our goal here is to:

Objectives

Notes before we begin:

Microsoft Orleans: Overview

In a nutshell

Microsoft Orleans: Overview

What is it?

Remote Procedure Calls

An abstraction over network communication

Remote Procedure Calls

Overview

RPC Concepts

What's at work here

RPC Concepts

Distributed systems

RPC Concepts

RPCs in a nutshell

RPC Concepts

Under the hood

RPC Concepts

Under the hood

RPC Concepts

Under the hood

RPC Concepts

Major parts

RPC Concepts

Insights

RPC Concepts

Drawbacks

Actors Model

How do we process concurrently without driving ourselves mad?

Actors Model

History

Actors Model

Nutshell concepts

Actors Model

Actors Model

Actors Model

Actors Implementation

Actors Model

Messages

Actors Model

Outcomes/Consequences

Orleans Getting Started

Zero to Go in....

Orleans Getting Started

Platform requirements

Orleans Getting Started

Hello, Orleans

Orleans Getting Started

Sidenote: Templates

Orleans Getting Started

Interface

Orleans Getting Started

IHelloWorld

namespace GrainInterfaces;

using System.Threading.Tasks;

public interface IHelloWorld : Orleans.IGrainWithIntegerKey
{
    Task<string> SayHello(string name);
}

Orleans Getting Started

Grain

Orleans Getting Started

HelloWorld

namespace Grains;

using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

using GrainInterfaces;

public class HelloWorld : Orleans.Grain, IHelloWorld
{
    private readonly ILogger _logger;

    public HelloWorld(ILogger<HelloWorld> logger) { _logger = logger; }

    public Task<string> SayHello(string name)
    {
        _logger.LogInformation("SayHello: name = '{name}', ", name);

        return Task.FromResult($"Hello, {name}, welcome to Orleans");
    }
}

Orleans Getting Started

Host

Orleans Getting Started

Program (host setup)

static async Task<IHost> StartSiloAsync(string[] args)
{
    var builder = new HostBuilder()
        .UseOrleans(c =>
        {
            c.UseLocalhostClustering()
            .Configure<ClusterOptions>(options =>
            {
                options.ClusterId = "dev";
                options.ServiceId = "HelloWorld";
            })
            .ConfigureLogging(logging => logging.AddConsole())
            .AddDashboard();
        });
    
    var host = builder.Build();
    
    await host.StartAsync();
    
    return host;
}

Orleans Getting Started

Program (main)

try
{
    var host = await StartSiloAsync(args);
    Console.WriteLine("\n\n Press Enter to terminate...\n\n");
    Console.ReadLine();
    
    await host.StopAsync();
    
    return 0;
}
catch (Exception ex)
{
    Console.WriteLine(ex);
    return 1;
}

Orleans Getting Started

Client

Orleans Getting Started

Program.cs - main

try
{
    var client = await ConnectClientAsync();
    await DoClientWorkAsync(client);
    Console.ReadKey();
    
    return 0;
}
catch (Exception e)
{
    Console.WriteLine($"\nException while trying to run client: {e.Message}");
    Console.WriteLine("Make sure the silo the client is trying to connect to is running.");
    Console.WriteLine("\nPress any key to exit.");
    Console.ReadKey();
    return 1;
}

Orleans Getting Started

Connecting to host cluster

static async Task<IClusterClient> ConnectClientAsync()
{
    var host = new HostBuilder()
        .UseOrleansClient(c => {
            c.UseLocalhostClustering()
            .Configure<ClusterOptions>(options =>
            {
                options.ClusterId = "dev";
                options.ServiceId = "HelloWorld";
            });
        })
        .ConfigureLogging(logging => logging.AddConsole())
        .Build();
    await host.StartAsync();
    
    Console.WriteLine("Client successfully connected to silo host \n");
    
    return host.Services.GetRequiredService<IClusterClient>();
}

Orleans Getting Started

Calling the grain

static async Task DoClientWorkAsync(IClusterClient client)
{
    var friend = client.GetGrain<IHelloWorld>(0);
    var response = await friend.SayHello("Good morning, HelloGrain!");
    
    Console.WriteLine($"\n\n{response}\n\n");
}

Orleans Concepts

What's important to know?

Orleans Concepts

Core concepts:

Orleans Concepts

Grains: Four facets of Virtual Actors

Orleans Concepts

Grain

Orleans Concepts

Grain identity

Orleans Concepts

Grain state

Orleans Concepts

Grain interface

Orleans Concepts

Message

Orleans Concepts

Silo

Orleans Concepts

Cluster

Orleans Concepts

Host

Orleans Concepts

Putting it all together

Orleans Concepts

Putting it all together

Orleans Concepts

Putting it all together

Orleans Concepts

Rules of thumb

Orleans Distributed System Design

What's important to know?

Orleans Distributed System Design

Things to think about

Orleans Distributed System Design

Approach

Orleans Distributed System Design

Contract-first

Orleans Distributed System Design

.NET-only

Orleans Distributed System Design

Actors-first

Orleans Distributed System Design

Asynchronous-first

More

Other topics

More

Other topics

Summary

What is Orleans?

Resources

Where to go to get more

Resources

Papers

Resources

Code/Github

Resources

Books

Credentials

Who is this guy?