ARM版 Visual Studio 2022 Preview 17.6.0 Preview 1.0 でついに MAUI がサポートされました!
詳細は後日レポート予定です。
Orleans の概要と基本構成のデプロイまで(目次)
目次
- 目次
- Orleans は何を解決するために生まれ、どのようなフレームワークなのか
- Orleans の 構成と重要なプリミティブ(構成要素)
- Orleans の構成要素:フロントエンド
- Orleans の構成要素:グレイン
- Orleans の構成要素:サイロ
- Orleans の基本的な構成を App Service にデプロイする(1)構成の確認
- Orleans の基本的な構成を App Service にデプロイする(2)VNet の設定
- Orleans の基本的な構成を App Service にデプロイする(3)App Service の プライベートポート
- Orleans の基本的な構成を App Service にデプロイする(4)動作確認
Orleans は何を解決するために生まれ、どのようなフレームワークなのか
記事はこちらです。
hiro128.hatenablog.jp
Orleans の 構成と重要なプリミティブ(構成要素)
記事はこちらです。
hiro128.hatenablog.jp
Orleans の構成要素:フロントエンド
記事はこちらです。
hiro128.hatenablog.jp
Orleans の構成要素:グレイン
記事はこちらです。
hiro128.hatenablog.jp
Orleans の構成要素:サイロ
記事はこちらです。
hiro128.hatenablog.jp
Orleans の基本的な構成を App Service にデプロイする(1)構成の確認
記事はこちらです。
hiro128.hatenablog.jp
Orleans の基本的な構成を App Service にデプロイする(2)VNet の設定
記事はこちらです。
hiro128.hatenablog.jp
Orleans の基本的な構成を App Service にデプロイする(3)App Service の プライベートポート
記事はこちらです。
hiro128.hatenablog.jp
Orleans の基本的な構成を App Service にデプロイする(4)動作確認
記事はこちらです。
hiro128.hatenablog.jp
Orleans の 構成と重要なプリミティブ(構成要素)
Orleans の構成
Orleans の構成は以下のようになっています。
Orleans のクラスターは1つの巨大なコンピューターのように取り扱われます。
スケールアウトやアップグレードによるインスタンス追加や、障害時のインスタンスの突然停止に対応するため、
サイロは、Container Apps、App Service、マネージド k8s などの SaaS にデプロイする前提となっています。
Orleans の基本的な動作は、以下の通りです。
- REST API が定義されたエンドポイントであるフロントエンドで、HTTP リクエストを受信します
- リクエストは適切なグレインにルーティングされグレインのメソッドが呼び出され、データがメモリ内にない場合はDBから取得し、レスポンスを返します
Orleans の重要なプリミティブ(構成要素)
Orleans の全体像を把握するために、重要な構成要素はフロントエンド、グレイン、サイロの3つです。
プリミティブ | 概要 |
---|---|
Frontend | Orleans の世界と外部とのゲートウェイ HTTP Request/Response と Grain Call/Response の変換を行います。 |
Grain | フロントエンドから呼び出す際のID(identity)、業務ロジック実装(behavior)、インメモリの状態(state)で構成されるエンティティ クラスターでホストされているグレインは、1 つのプロセス内にあるかのように相互に通信できます。 |
Silo | グレインをホストするインスタンス クラスターとして実行され、サイロ同士は互いに連携して作業を分散し、失敗を検出して復旧できます。 |
次の記事はこちらです。
hiro128.hatenablog.jp
Orleans の基本的な構成を App Service にデプロイする(2)VNet の設定
構成図
構成では、フロントエンドのみパブリックアクセス可能、2つのサイロとストレージはプライベートアクセスのみ可能としますが、プライベートアクセスはリージョン VNet 統合とプライベートエンドポイントで実現します。
そのための VNet の設定は以下のようになります。
アドレス空間
接続デバイス(プライベートエンドポイント)
サブネット
次の記事はこちらです。
hiro128.hatenablog.jp
Orleans は何を解決するために生まれ、どのようなフレームワークなのか
目次
- 目次
- 古典的なWebアプリの問題点
- 対策としてキャッシュ、キューなどを追加するも新たな問題が
- 根本解決のためのアプローチ(Orleans のコンセプト)
- 結局 Orleans とは
- Orleans のメリット
古典的なWebアプリの問題点
- 読み取り要求のたびにデータベースにアクセスするため、 データベースの負荷が大きい
- アプリのインスタンスの状態をお互いが把握できず、データベースへの書き込み競合が発生する
- 各々のアプリのインスタンスが状態を個別に持ちリソースの効率が悪い。
対策としてキャッシュ、キューなどを追加するも新たな問題が
- 読み取り要求のデータベース負荷対策としてキャッシュを追加。代わりに、キャッシュの一貫性の問題が発生
- データベースへの書き込み競合対策としてキューを追加。代わりに、非同期書き込みの待ちが発生
問題は軽減しているが、インフラを追加して厄介ごとをオフロードしているだけなので根本的な解決ではない…
スケーラビリティも確保できていない
根本解決のためのアプローチ(Orleans のコンセプト)
- アプリインスタンスがお互いに会話し互いに連携することで分散アプリの問題を解決する
- データベースを唯一の「真実のソース」とし、キャッシュやキューなどの余計なインフラ自体をなくす
これによって
- 高スループット
- 低レイテンシー
- 高スケーラビリティ
が確保できることをねらって開発されました。
結局 Orleans とは
Orleans は、アプリケーションのフロントエンド と永続化ストレージ(DBなど)の間のステートフルでスマートな中間層を提供するフレームワークです。
Orleans のメリット
- DB への書き込み競合の考慮が不要
- キャッシュ不要
- Appインスタンス間の一貫性考慮が不要
- Appインスタンスを追加すれば自動でクラスターが構成される
分散アプリケーションを開発するときに発生するいろいろな面倒なことについて、
いい感じで面倒を見てくれるので、メリットだけを享受することができます。
Teams など超大規模サービスでの実績もある安定したフレームワークです
次の記事はこちらです。
hiro128.hatenablog.jp
Orleans の基本的な構成を App Service にデプロイする(1)構成の確認
方針
Orleans の基本的な構成のデプロイを App Service にデプロイしてみましょう。
基本的な方針を以下の通りとします
- フロントエンドのみパブリックアクセス可能
- 2つのサイロとストレージはプライベートアクセスのみ可能とする
- プライベートアクセスはリージョン VNet 統合とプライベートエンドポイントで実現する
実際の構成は以下のようになります。
それぞれのリソースが Orleans のどの構成要素に相当するか分かりやすくするため概念図との対比にしました。
構成
役割 | リソース | パブリック アクセスの受信 |
プライベート アクセスの受信 |
プライベート エンドポイント |
リージョン VNet 統合 |
WebSocket |
フロントエンド | App Service | ○ | X | X | ○ | ○(ポート数:2) |
サイロ01 | App Service | X | ○ | ○ | ○ | ○(ポート数:2) |
サイロ02 | App Service | X | ○ | ○ | ○ | ○(ポート数:2) |
永続化ストレージ | Table Storage | X | ○ | ○ | ーーー | ーーー |
次の記事はこちらです。
hiro128.hatenablog.jp
Orleans の 永続データオブジェクト
Orleans では、グレインの永続化とサイロのメンバーシップ管理用のテーブルとして、永続データオブジェクトを利用します。
Microsoft によってメンテされているグレインの永続化ストレージパッケージは以下です。
- ADO.NET
- Azure Blob Storage、Azure Table Storage、Azure CosmosDB などの Azure Storage
- Amazon DynamoDB
learn.microsoft.com
Microsoft によってメンテされているサイロのメンバーシップ管理用テーブルのパッケージは以下です。
- ADO.NET
- Azure Blob Storage、Azure Table Storage、Azure CosmosDB などの Azure Storage
- Amazon DynamoDB
- Apache ZooKeeper
- Consul IO
Azure Table Storage を使用した場合の実例
例として、グレインの永続化ストレージとして Azure Table Storage を使用した場合について見てみます。
「orleanspoc」という名前のストレージアカウントを作成し、下記のように接続文字列を指定してサイロを構成すると初回に自動的にテーブルが作成されます。
グレインの状態の永続化用テーブル OrleansGrainState の指定
.AddAzureTableGrainStorage( "PocStore", options => options.ConfigureTableServiceClient(connectionString) )
サイロメンバーシップの管理用のテーブル OrleansSiloInstances の指定
.UseAzureStorageClustering(options => options.ConfigureTableServiceClient(connectionString))
グレインの状態の永続化用テーブル OrleansGrainState
レコードを確認すると以下のようになっています。
App Service にサイロをデプロイした時のレコードを確認して各項目について調べてみました。
列名 | 値のソース、形式 | 説明 |
---|---|---|
PartitionKey | [ClusterOption.ServiceID]_[グレイン名のプレフィックス]_[連番] | 永続化したグレインを一意に特定するキー |
RowKey | PersistentStateAttribute.StateName | グレインは複数の状態を持てる。グレインが保持している状態を特定するキー |
Timestamp | タイムスタンプ | タイムスタンプ |
Data Data1 Data2 |
シリアライズかつバイナリ化されたグレインが保持している状態の実体 1列に収まらなければ、連番なし、1、2 … N のように複数列に格納される |
シリアライズかつバイナリ化されているため直接レコードを見ても中身はわからない状態になっている 規定では Orleans.Storage.JsonGrainStorageSerializer が利用される 参考:Orleans でのシリアル化の概要 | Microsoft Learn |
サイロメンバーシップの管理用のテーブル OrleansSiloInstances
レコードを確認すると以下のようになっています。
App Service にサイロをデプロイした時のレコードとソースコードなどを確認して各項目について調べてみました。
列名 | 値のソース、形式 | 説明 |
---|---|---|
PartitionKey | ClusterOption.ClusterId | サイロとクライアントがメンバーシップテーブルでお互いを見つけるためのキー |
RowKey | [ConfigureEndpoints のパラメーター advertisedIP] -[ConfigureEndpoints のパラメーター siloPort] -[Generation] |
advertisedIP:クラスタリングに使用される IP アドレス(サイロのエンドポイントの IP アドレス) siloPort:サイロ間通信の際に当該のサイロが使用するポート(サイロのエンドポイントのポート) Generation:(epoch)サイロインスタンスの世代。2022/1/1 00:00:00 (UTC) を0とした現時刻 (UTC) までの Tick 数 |
Timestamp | タイムスタンプ | タイムスタンプ |
Address | EndpointOptions.AdvertisedIPAddress | クラスタリングに使用される IP アドレス |
DeploymentId | PartitionKey の値 | Orleans 2.0以前は DeploymentId と呼ばれていた名残り |
Generation | 2022/1/1 00:00:00 (UTC) を0とした現時刻 (UTC) までの Tick 数 | サイロインスタンスの世代。learn のドキュメントでは「epoch」と呼称されている 参考:Orleans でのクラスターの管理 | Microsoft Learn |
HostName | サイロの DNS ホスト名 | Dns.GetHostName() と同じ結果となる。サイロの起動時に設定される |
IAmAliveTime | DateTimeOffset | 当該のサイロが生きていることを最後に報告した日時 Orleans ランタイムによる死活診断やトラブルシューティング時に利用する |
InstanceName | 古いカラムのため未調査 | 後方互換性のために残されている古いカラム。 |
Port | EndpointOptions.SiloPort | サイロ間通信(silo-to-silo)の際に当該のサイロが使用するポート(サイロのエンドポイントのポート)規定値は 11111 |
ProxyPort | EndpointOptions.GatewayPort | サイロからクライアント(この文脈では REST API <-> Grain Call のフロントエンドのこと)への TCP ポート。サイロの起動時に設定される。規定値は 30000 |
RoleName | 実行中のアセンブリの名前。 | |
SiloName | サイロ ホストが付けたサイロ名。サイロの起動時に設定。 | |
StartTime | DateTimeOffset | サイロインスタンスのが起動した日時 |
Status | サイロの状態 | 状態の詳細は右記を参照:SiloStatus 列挙型 (Orleans.Runtime) | Microsoft Learn メンバーシッププロトコルで管理される。 |
SuspectingSilos | [サイロの IPアドレス]-[サイロの Port]@Generation | 当該のサイロが Active ではないことを疑っているサイロのリスト。メンバーシッププロトコルで管理される。 |
SuspectingTimes | DateTimeOffset | 当該のが Active ではないことに対する疑いが生じた日時 |
UpdateZone | Azure Cloud Services では利用されていたが、App Service での利用状況は不明 | |
MembershipVersion | Int64 | TableVersion の場合のみ、現在のメンバーシップ構成の最新バージョン。MembershipEntry の 場合は null |