Orleans Microsoft のアクターベースの分散フレームワーク

1. アクターモデルの動作原理

        アクター モデルは同時プログラミング モデルであり、メッセージ パッシングに基づいて実装され、軽量の同時実行モデルです。アクター モデルでは、各アクターはメッセージを送受信し、一部のローカル操作を実行できる独立した実行ユニットですが、他のアクターの状態に直接アクセスすることはできません。

アクター モデルの基本的な動作原理は次のとおりです。
1. 各アクターは一意の識別子を持ち、メッセージを送受信できます。
2. アクターはメッセージ パッシングを通じて通信し、各アクターには受信したメッセージを保存するためのメッセージ キューがあります。
3. アクターは一部のローカル操作を実行できますが、他のアクターの状態に直接アクセスすることはできません。他のアクターの状態にアクセスしたい場合は、メッセージを送信して他のアクターにデータを要求する必要があります。
4. アクターはメッセージを受信すると、メッセージ処理ロジックに従って対応する操作を実行し、他のアクターにメッセージを送信できます。
5. アクター間の通信は非同期です。つまり、メッセージを送信するアクターは、メッセージを受信するアクターがメッセージの処理を完了するのを待ってから実行を続行する必要はありません。
6. Actor モデルでは、すべての操作がメッセージ パッシングに基づいて実装されるため、競合状態やデッドロックなどの同時実行の問題を回避できます。

アクターモデルの仕組み

        全体として、アクター モデルは、同時実行の問題を複数の独立した実行ユニットに分解することにより、非常に柔軟で効率的な同時プログラミング モデルを実装します。競合状態やデッドロックなどの一般的な同時実行の問題を回避し、分散システムでの同時実行の問題を適切に処理できます。

2. オルレアンの紹介

        Orleans は、Microsoft が提供するオープンソースの分散型アクターベースのモデリング フレームワークです。

        Orleans は、信頼性が高くスケーラブルな分散アプリケーションを構築するためのクロスプラットフォーム フレームワークです。分散アプリケーションは、複数のプロセスにまたがるアプリケーションとして定義され、多くの場合、ピアツーピア通信を使用してハードウェアの境界を越えます。Orleans は、単一のオンプレミス サーバーからクラウド内の数十万の分散型高可用性アプリケーションまで拡張します。Orleans は、C# のおなじみの概念とイディオムをマルチサーバー環境に拡張します。Orleans は設計上、弾力的にスケーラブルです。ホストがクラスターに参加すると、新しいアクティブ化を受け入れることができます。スケールインまたはマシンの障害によりホストがクラスターから離れると、そのホスト上の以前のアクティベーションは、必要に応じて残りのホストで再アクティベートされます。Orleans クラスターは単一ホストにスケールダウンできます。エラスティック スケーリングを有効にするために使用される同じプロパティにより、フォールト トレランスも有効になります。クラスターは障害を自動的に検出し、障害から迅速に回復します。

        Orleans の主な設計目標の 1 つは、共通のパターンと API のセットを提供することで、分散アプリケーション開発の複雑さを簡素化することでした。単一サーバー アプリケーションの開発に慣れている開発者は、Orleans の使用に簡単に切り替えて、回復力とスケーラブルなクラウド ネイティブ サービスやその他の分散アプリケーションを構築できます。このため、Orleans は「分散 .NET」と呼ばれることが多く、クラウド ネイティブ アプリケーションの構築に最適なフレームワークです。

        今日のコンピューター環境では、マルチスレッド プログラミングは避けられません。マルチスレッドによってもたらされる多くの利点は、プログラミングに多くの欠点ももたらします。たとえば、マルチスレッド環境では、操作データのアトミック性をどのように維持するかが問題になります。

        Orleans が採用した方法は、Actor モデルの原理を利用して、このクラスの「作成」処理から「破棄」処理までの実行処理と「途中で呼び出す方法」を保証するクラス設計であり、これら 3 つの「処理」はいつどこで呼び出されても同じスレッドで実行されます。このようにして、このクラスを指す変数の「ダーティ リード」を心配することなく、このクラスのメソッドを大胆に変更して呼び出すことができます。

        Orleans モデルでは、各アクターには Grain と呼ばれる、それを表す特別なクラスがあり、この Grain クラスが、シミュレートされたコミュニケーション シーンにおける「人」になります。

1. 穀物とは

        穀物は、オルレアンのいくつかのプリミティブのうちの 1 つです。アクター モデルに関する限り、グレインは仮想アクターです。Orleans アプリケーションの基本的な構成要素は穀物です。グレインは、ユーザー定義の ID、動作、および状態を持つエンティティです。次の粒子の視覚的表現を考えてみましょう。

 

        グレイン ID は、複数のタイプで使用できるユーザー定義のキーであり、グレインを常に呼び出し可能にします。グレインには、任意のストレージ システムに保存できる揮発性または永続的な状態データを含めることができます。したがって、グレインは暗黙的にアプリケーションの状態を分割し、自動スケーラビリティを可能にし、障害からの回復を簡素化します。グレインがアクティブな場合、グレイン状態がメモリ内に保持されるため、レイテンシが短縮され、データ ストアがオフロードされます。

        グレインのインスタンス化は、Orleans ランタイムによってオンデマンドで自動的に実行されます。しばらく使用されなかったグレインは、リソースを解放するためにメモリから自動的に削除されます。これが可能なのは、グレインがメモリにロードされているかどうかに関係なく呼び出すことができる安定した ID を持っているためです。これにより、呼び出し側はどの時点でもグレインがインスタンス化されたサーバーを知る必要がないため、透過的な方法で障害から回復することもできます。グレインには管理されたライフサイクルがあり、Orleans ランタイムはオンデマンドでグレインのアクティブ化/非アクティブ化と配置/配置を行います。これにより、開発者はあたかもすべてのグレインがメモリ内にあるかのようにコードを書くことができます。

        マルチスレッドによって引き起こされる「リソース競合」の問題を解決するために、Orleans は各グレイン クラスが Orleans フレームワーク内の次の動作仕様に準拠していることを保証します。

  A.同じグレイン クラス インスタンスに送信されたメッセージはすべて、固定スレッドで実行されます。
  B.粒度クラスは、メッセージを受信した順序に従って順番に処理します。どの時点でも、グレイン インスタンスは 1 つのメッセージのみを処理します。
  C.インスタンス自体によってのみアクセスできる穀物インスタンス内のフィールド プロパティ。外部の世界からはアクセスできません。

 2. サイロとは何ですか?

        サイロは、オルレアン プリミティブのもう 1 つの例です。サイロには 1 つ以上のグレインが収容されます。Orleans ランタイムは、アプリケーションのプログラミング モデルを実装します。

        通常、サイロのグループは、スケーラビリティとフォールト トレランスを実現するためのクラスターとして動作します。クラスターとして動作する場合、サイロは相互に調整して作業を分散し、障害を検出して回復します。ランタイムにより、クラスター内でホストされているグレインが単一のプロセス内にあるかのように相互に通信できるようになります。次の図は、クラスター、サイロ、およびグレイン間の関係を視覚化したものです。

上の図は、クラスター、サイロ、およびグレインの関係を示しています。任意の数のクラスターを形成でき、各クラスターには 1 つ以上のサイロが含まれ、各サイロには 1 つ以上のグレインが含まれます。

コア プログラミング モデルに加えて、サイロは、タイマー、リマインダー (永続タイマー)、永続性、トランザクション、ストリームなどの一連のランタイム サービスをグレインに提供します。

3. オルレアンでできること

        Orleans は、クラウド ネイティブ アプリケーションを構築するためのフレームワークです。最終的に拡張する必要がある .NET アプリケーションを構築する場合は、Orleans の使用を検討してください。Orleans の用途は無数にあるように思えますが、ここでは最も一般的なもののいくつかを紹介します: ゲーム、銀行業務、チャット アプリ、GPS 追跡、株取引、ショッピング カート、投票アプリなど。Microsoft は、Azure、Xbox、Skype、Halo、PlayFab、Gears of War、およびその他の多くの内部サービスで Orleans を使用しています。Orleans の多くの機能により、さまざまなアプリケーションで簡単に使用できます。

 3. Orleans の簡単な使用例

Grain を使用して単純な URL 短縮機能を実装するプロジェクトを作成する

#创建新web项目
dotnet new web -o UrlShortener -f net7.0

#进入项目文件夹,打开编辑器
cd UrlShortener
code .

 orleans コンポーネントをプロジェクトに追加します

#将 Orleans 添加到项目
dotnet add package Microsoft.Orleans.Server -v 7.0.0

Program.cs ファイルの先頭に参照を追加します。

using Microsoft.AspNetCore.Http.Extensions;
using Orleans.Runtime;

1. 穀物クラスを作成する

        まず、program.cs ファイルの最後に、IGrainWithStringKey を継承して設定と読み込みを実装するインターフェイスを追加します。

public interface IUrlShortenerGrain : IGrainWithStringKey
{
    Task SetUrl(string shortenedRouteSegment, string fullUrl);
    Task<string> GetUrl();
}

次に、UrlShortenerGrain クラスを作成し、このインターフェイスを実装します。

public class UrlShortenerGrain : Grain, IUrlShortenerGrain
{
    private KeyValuePair<string, string> _cache;

    public Task SetUrl(string shortenedRouteSegment, string fullUrl)
    {
        _cache = new KeyValuePair<string, string>(shortenedRouteSegment, fullUrl);
        return Task.CompletedTask;
    }

    public Task<string?> GetUrl()
    {
        return Task.FromResult(_cache.Value);
    }
}

2. レシーバーの作成と構成 

Program クラスの先頭で、Orleans を使用するようにビルダー コードをリファクタリングします。完成したコードは次の例のようになります。

var builder = WebApplication.CreateBuilder();

builder.Host.UseOrleans(siloBuilder =>
{
    siloBuilder.UseLocalhostClustering();
});

var app = builder.Build();

        次に、粒度ファクトリのインスタンスを取得する必要があります。Orleans は、グレインの識別子を使用してグレインの作成と取得を管理するデフォルトのグレイン ファクトリを提供します。var app = builder.Build(); を呼び出した後、次のコード行を追加してグレイン ファクトリを取得し、グレイン ファクトリという名前の変数に格納します。

var grainFactory = app.Services.GetRequiredService<IGrainFactory>();

3. 長いURLの受信ルートを作成する

最初に「Hello, world」を出力するコードを変更して、長い URL を受け入れ、短い URL を返す準備をします。

app.MapGet("/shorten/{*path}",
    async (IGrainFactory grains, HttpRequest request, string path) =>
{
    return Results.Ok();
});

この時、200のnull値が返されるのですが、短いURLパスを返すように改良されました。

app.MapGet("/shorten/{*path}",
async (IGrainFactory grains, HttpRequest request, string path) =>
{
    var shortenedRouteSegment = Guid.NewGuid().GetHashCode().ToString("X");
    var shortenerGrain = grains.GetGrain<IUrlShortenerGrain>(shortenedRouteSegment);
    await shortenerGrain.SetUrl(shortenedRouteSegment, path);
    var resultBuilder = new UriBuilder(request.GetEncodedUrl())
    {
        Path = $"/go/{shortenedRouteSegment}"
    };

    return Results.Ok(resultBuilder.Uri);
});

上記のコードはいくつかのタスクを実行します。

  • まず、GUID を使用して、ハッシュ コードから 16 進文字列としてランダムな短縮ルート セグメントを作成します。
  • 次に、グラニュール ファクトリは、短縮されたルート セグメントを識別子として使用して、新しいグラニュールを作成します。
  • 詳細インスタンスには、短縮されたルート セグメントと元の宛先 URL が保存され、後で取得できるようになります。
  • 最後に、短縮されたルート セグメントを含む新しい URL が組み立てられ、ユーザーに返されます。

4. 短い URL にアクセスしたときに、対応する長い URL にリダイレクトするルーティング パスを作成します。

app.MapGet("/go/{shortenedRouteSegment}",
    async (IGrainFactory grains, string shortenedRouteSegment) =>
{
    var shortenerGrain = grains.GetGrain<IUrlShortenerGrain>(shortenedRouteSegment);
    var url = await shortenerGrain.GetUrl();

    return Results.Redirect(url);
});

このコードは、ユーザーのリクエストを処理するために次のタスクを実行します。

  • 短縮 URL 名をキーとして使用して、指定された短縮 URL のリダイレクト情報を保持するグレインをグレイン ファクトリから取得します。
  • グレインから完全な URL 文字列を取得します。
  • 適切な URL が見つかった場合、ユーザーはそこにリダイレクトされます。それ以外の場合は、404 が返されます。

5. テストを実行する

dotnet run

 たとえば、{localhost}/shorten/https://blog.csdn.net/zhujisoft にアクセスし、ショート パス「http://localhost:5205/go/AB39050D」を取得します。

短いパス http://localhost:5205/go/AB39050D にアクセスすると、長い URL アドレスにリダイレクトされ、グレインを使用して単純な変換機能を実現できます。

 6. 状態を維持し、粒度のあるデータを保存してみます

状態を永続化するオブジェクトは、グレイン コンストラクターで宣言し、PersistentState プロパティで装飾することで定義できます。この属性で修飾されたオブジェクトは、前述の API メソッドにアクセスできます。
PersistentState プロパティは 2 つのパラメーターを受け入れます。

  • 名前: 状態オブジェクトの名前を定義します。
  • StorageName: オブジェクトを保存するストレージ プロバイダーを定義します。
public class UrlShortenerGrain : Grain, IUrlShortenerGrain
{
    private readonly IPersistentState<KeyValuePair<string, string>> _cache;

    public UrlShortenerGrain(
        [PersistentState(
            stateName: "url",
            storageName: "urls")]
            IPersistentState<KeyValuePair<string, string>> state)
    {
        _cache = state;
    }
}

7.穀物の保管方法を設定する

builder.Host.UseOrleans(siloBuilder =>
{
    siloBuilder.UseLocalhostClustering();
    siloBuilder.AddAzureBlobGrainStorage("urls",
        // Recommended: Connect to Blob Storage using DefaultAzureCredential
        options =>
        {
            options.ConfigureBlobServiceClient(new Uri("https://<your-account-name>.blob.core.windows.net"),
                new DefaultAzureCredential());
        });
        // Connect to Blob Storage using Connection strings
        // options => options.ConfigureBlobServiceClient(connectionString));
});

         ストレージ プロバイダーの例には、従来の SQL データベース、Blob Storage などのさまざまな Azure サービス、Amazon DynamoDb などのその他のクラウド リソースが含まれます。これらのプロバイダーは、さまざまな NuGet パッケージを通じて利用できます。Orleans は、独自のストレージ プロバイダーを追加するための拡張ポイントも提供します。

わかりやすくするために、この例ではメモリ内ストレージを使用します。

builder.Host.UseOrleans(siloBuilder =>
{
    siloBuilder.UseLocalhostClustering();
    siloBuilder.AddMemoryGrainStorage("urls");
});

グレイン コンストラクターと使用法を更新する

public async Task SetUrl(string shortenedRouteSegment, string fullUrl)
{
    _cache.State = new KeyValuePair<string, string>(shortenedRouteSegment, fullUrl);
    await _cache.WriteStateAsync();
}

public Task<string> GetUrl()
{
    return Task.FromResult(_cache.State.Value);
}

それ以来、アプリケーションは永続的な状態をサポートするようになりました。

4. 参考記事

1. Orleans トレーニングの概要 | Microsoft Learn

2.導入 - トレーニング | Microsoft Learn

3.アクターモデルの動作原理 - Tengke IT Education 公式ウェブサイト

4. Orleans_c# の概要 orleans フレームワーク コンポーネント_liyan530 のブログ - CSDN ブログ

おすすめ

転載: blog.csdn.net/zhujisoft/article/details/131716423