Orleans ランタイムは、既定では、クラスター内でグレインのアクティブ化を 1 つだけ作成します。 これは Virtual Actor モデルの最も直感的な式です。各グレインは、一意の型/ID を持つエンティティに対応します。 ただし、アプリケーションがシステム内の特定のエンティティに関連付けられていない機能ステートレス操作を実行する必要がある場合があります。 たとえば、クライアントが圧縮されたペイロードを含む要求を送信し、処理のためにターゲット グレインにルーティングする前に展開が必要な場合、このような展開/ルーティング ロジックは特定のエンティティに関連付けられず、簡単にスケールアウトできます。
StatelessWorkerAttributeをグレイン クラスに適用すると、そのクラスのグレインをステートレス ワーカー グレインとして扱う必要があることをOrleans ランタイムに示します。 ステートレスワーカーのグレインは、通常のグレイン クラスとは異なり、次のような特徴を持ちます。これにより、実行方法が大きく異なります。
- Orleans ランタイムは、クラスター内の異なるサイロに対してステートレス ワーカー グレインの複数のアクティブ化を作成できます。
- ステートレス ワーカー グレインは、サイロに互換性がある限りローカルで要求を実行するため、ネットワークやシリアル化のコストは発生しません。 ローカル サイロに互換性がない場合、要求は互換性のあるサイロに転送されます。
-
Orleans ランタイムは、既存のワーカー グレインがビジー状態の場合に、ステートレス ワーカー グレインの追加のアクティブ化を自動的に作成します。 オプションの
maxLocalWorkers
引数を使用して明示的に指定しない限り、サイロあたりのアクティブ化の最大数は、既定ではマシン上の CPU コア数によって制限されます。 - ポイント 2 と 3 により、ステートレス ワーカー グレインのアクティブ化は個別にアドレス指定できません。 ステートレス ワーカー グレインに対する後続の 2 つの要求は、異なるアクティブ化によって処理される可能性があります。
ステートレスワーカーグレインを使用すると、実際の負荷に応じて自動的に拡大・縮小が行われるグレインアクティベーションの管理プールを簡単に作成できます。 ランタイムは、使用可能なステートレス ワーカー グレインのアクティブ化を、常に同じ順序でスキャンします。 このため、要求は待機状態のローカルアクティベーションが最初に見つかったものに常に送信され、以前のすべてのアクティベーションがビジー状態の場合にのみ最後のアクティベーションへと進みます。 すべてのアクティブ化がビジー状態で、アクティブ化の制限にまだ達していない場合は、リストの最後尾にアクティブ化をさらに作成して、そこに要求をディスパッチします。 つまり、ステートレス ワーカー グレインへの要求頻度が増加し、既存のアクティベーションがすべてビジー状態になると、ランタイムはアクティベーションのプールを制限いっぱいまで拡張します。 逆に、負荷が低下し、処理できるアクティブ化の数が少ない場合、リストの末尾にあるアクティブ化は要求を受け取りません。 これらは使用されていない状態になり、最終的には通常のアクティベーション収集プロセスによって非アクティブ化されます。 したがって、アクティブ化のプールは最終的に負荷に合わせて縮小されます。
次の例では、既定のアクティブ化の最大数制限を指定してステートレス ワーカー グレイン クラス MyStatelessWorkerGrain
を定義します。
[StatelessWorker]
public class MyStatelessWorkerGrain : Grain, IMyStatelessWorkerGrain
{
// ...
}
ステートレス ワーカー グレインの呼び出しは、他のグレインの呼び出しと同じです。 唯一の違いは、ほとんどの場合、 0
や Guid.Emptyなど、1 つのグレイン ID を使用するということです。 複数のステートレス ワーカー グレイン プール (ID ごとに 1 つ) が必要な場合は、複数のグレイン ID を使用できます。
var worker = GrainFactory.GetGrain<IMyStatelessWorkerGrain>(0);
await worker.Process(args);
この例では、サイロごとに1つのみアクティブ化されるステートレスワーカーグレインクラスを定義します。
[StatelessWorker(1)] // max 1 activation per silo
public class MyLonelyWorkerGrain : ILonelyWorkerGrain
{
//...
}
ターゲットグレインクラスの再入性はStatelessWorkerAttributeによって変更されることはありません。 他のグレインと同様に、ステートレス ワーカー グレインは既定では再入不可能です。 グレイン クラスに ReentrantAttribute を追加することで、明示的に再入可能にすることができます。
状態コード
"ステートレスワーカー" の "ステートレス" 部分は、ステートレスワーカーが状態を持てないことや、単に機能操作を実行することに限定されていることを意味するわけではありません。 他のグレインと同様に、ステートレス ワーカー グレインは、必要な状態をメモリ内に読み込んで保持することができます。 ただし、クラスター内の同じサイロと異なるサイロでステートレス ワーカー グレインの複数のアクティブ化を作成できるため、さまざまなアクティブ化によって保持される状態を調整する簡単なメカニズムはありません。
いくつかの便利なパターンでは、ステートレスなワーカーが状態を保持することがあります。
スケールアウトされたホット キャッシュアイテム
高いスループットを経験しているホット・キャッシュ項目に対して、ステートレス・ワーカー・グレインで各項目を保持することには次の利点があります。
- サイロ内およびクラスター内のすべてのサイロ間で自動的にスケールアウトされます。
- これにより、クライアント ゲートウェイ経由でクライアント要求を受信したサイロでデータが常にローカルに使用可能になり、別のサイロへの追加のネットワーク ホップなしで要求に応答できるようになります。
Reduce スタイルの集計
クラスター内にある特定の種類のグレインすべてにわたって、特定のメトリックをアプリケーションで計算し、その集計を定期的にレポートする必要がある場合があります。 たとえば、ゲーム マップごとのプレイヤー数や VoIP 呼び出しの平均継続時間のレポートなどがあります。 数千または数百万のグレインのそれぞれがメトリックを 1 つのグローバル アグリゲーターに報告した場合、アグリゲーターはすぐに過負荷になり、レポートの洪水を処理できなくなります。 別の方法として、このタスクを 2 段階 (またはそれ以上) の reduce スタイルの集計に変換します。 集計の第一段階では、レポートグレインがそのメトリックをステートレスワーカーの事前集計グレインに送信します。 Orleans ランタイムは、各サイロでステートレスワーカーグレインを複数のインスタンスとして自動的に作成します。 Orleansリモート呼び出しやメッセージのシリアル化なしでローカルでこのような呼び出しをすべて処理するため、この集計のコストはリモートの場合よりも大幅に少なくなります。 これで、各事前集計ステートレスなワーカー グレインのアクティベーションは、独立して、または他のローカル アクティベーションと連携して、集計されたレポートをグローバルな最終アグリゲーター(または必要に応じて別の削減レイヤー)に送信できます。
.NET