グレインの役割
グレインはユーザー定義のID(identity)、業務ロジック(behavior)、およびインメモリの状態(state)をカプセル化し、他のグレインとメッセージを送受信したり、クライアントからの要求に対するレスポンスを返します。
グレインの取得
グレインの物理的な場所に関して開発者は意識不要です。
同一インターフェースで指定したグレインのプロキシオブジェクトを同一の GrainID で取得すると、どのフロントエンド(クライアント)から呼び出したとしても同一のグレインの実体が呼び出されます。
グレインの実装例
インターフェース
using System.Threading.Tasks; using Orleans; namespace OrleansPoc { public interface IWriteLargeData : Orleans.IGrainWithGuidKey { Task<string> WriteLargeData(); } } |cs|< ** 実装 >|cs| using Grains.Status; using Microsoft.Extensions.Logging; using OrleansPoc.Sevices; using System.Reflection.Emit; using System.Threading.Tasks; using Orleans.Runtime; namespace OrleansPoc { public class WriteLargeDataGrain : Orleans.Grain, IWriteLargeData { private readonly ILogger _logger; private readonly IPersistentState<WriteLargeDataState> _largeData; public WriteLargeDataGrain( [PersistentState("largeData", "PocStore")] IPersistentState<WriteLargeDataState> largeData, ILogger<HelloGrain> logger ) { _largeData = largeData; _logger = logger; } async Task<string> IWriteLargeData.WriteLargeData() { _logger.LogInformation($"\n{DateTime.Now} WriteLargeData recieved."); var largeData = ""; largeData = Enumerable.Range(0, 30000).Select(i => "ABCDEFGHIJKLMNOPQRSTUVWXYZ").Aggregate((x, y) => $"{x},{y}"); _largeData.State.LargeData = largeData; await _largeData.WriteStateAsync(); return "Grain Status の書き込みが終了しました。"; } } }
グレインのその他の特長
- グレインはシングルスレッド実行が保証され、ロックや一貫性の問題の考慮が不要です。
- 個々のグレインは Orleans のランタイムによって、開発者は意識することなく、必要に応じてページイン(アクティブ化)・ページアウト(非アクティブ化)されるため、メモリの使用量やグレインのロードバランシングは動的に最適化されます。
- GrainID によって呼び出されるグレインの参照(プロキシオブジェクト)は、グレインの論理的なアイデンティティのみを含んでいます。アプリケーションコードはグレインの物理的な位置を意識することなくグレインと通信できます。グレインの物理的な位置は、Orleans のランタイムによって、障害やリソース管理、または呼び出された時点での当該のグレインが非アクティブになっているなどの理由で、時間の経過とともに変化する可能性がありますが、それを開発者がアプリケーションコードによって管理する必要はなく、意識する必要もありません。
次の記事はこちらです。
hiro128.hatenablog.jp