次の方法で共有


Azure Cosmos DB .NET SDK のベスト プラクティス

適用対象: NoSQL

この記事では、Azure Cosmos DB .NET SDK を使用する上でのベスト プラクティスについて説明します。 これらのプラクティスに従うことで、待機時間、可用性を向上させ、全体的なパフォーマンスを向上させることができます。

Azure Cosmos DB エンジニアからの .NET SDK の使用の詳細については、次のビデオをご覧ください。

チェック リスト

チェックボックス サブジェクト 説明
SDK バージョン 最適なパフォーマンスを実現するために、常に最新バージョンの Azure Cosmos DB SDK を使用します。
シングルトン クライアント パフォーマンスを向上させるには、ご自身のアプリケーションの有効期間中に CosmosClient単一インスタンスを使用します。
リージョン 待機時間を短縮するには、可能な限り、Azure Cosmos DB アカウントと同じ Azure リージョン でアプリケーションを実行してください。 2 から 4 のリージョンを有効にし、複数のリージョンでアカウントをレプリケートして、可用性を最大限に高めます。 運用環境ワークロードの場合は、サービスマネージド フェールオーバーを有効にします。 この構成がない場合、リージョン接続がないために手動フェールオーバーが成功しないため、書き込みリージョンの停止のすべての期間、アカウントの書き込み可用性が失われます。 .NET SDK を使用して複数のリージョンを追加する方法については、 このチュートリアルを参照してください。
可用性とフェールオーバー v3 SDK で ApplicationPreferredRegions または ApplicationRegion を設定し、優先リージョン リストを使用して v2 SDK の PreferredLocations を設定します。 フェールオーバー中に、書き込み操作が現在の書き込みリージョンに送信され、すべての読み取りが優先リージョン リスト内の最初のリージョンに送信されます。 リージョン内フェールオーバー メカニズムの詳細については、可用性に関するトラブルシューティング ガイドを参照してください。
CPU クライアント コンピューターにリソースがないため、接続/可用性の問題が発生する可能性があります。 Azure Cosmos DB クライアントを実行しているノードで CPU 使用率を監視し、使用率が高い場合はスケールアップ/スケールアウトします。
Hosting 最適なパフォーマンスを実現するには、可能な限り Windows 64 ビットのホスト処理を使用します。 直接モードの待機時間に敏感な運用環境ワークロードの場合、可能な限り、少なくとも 4 コアかつ 8 GB メモリの VM を使用することを強くお勧めします。
接続モード 最適なパフォーマンスを得るための ダイレクト モード を使用します。 手順については、 V3 SDK のドキュメント または V2 SDK のドキュメントを参照してください
ネットワーク 仮想マシンを使用してアプリケーションを実行する場合は、VM で高速ネットワークを有効にして、高トラフィックが原因で発生するボトルネックを解消し、待機時間や CPU ジッターを減らします。 また、CPU 使用率の上限が 70%を超えるハイエンド仮想マシンの使用を検討することもできます。
一時的なポートの不足 スパースまたは散発的な接続の場合は、IdleConnectionTimeoutPortReuseModePrivatePortPool に設定します。 IdleConnectionTimeout プロパティは、未使用の接続を閉じるまでの時間を制御するのに役立ちます。 これにより、使用されない接続の数が減ります。 既定では、アイドル状態の接続は無期限に開いた状態になります。 10 分以上の値を指定する必要があります。 推奨値は 20 分から 24 時間です。 PortReuseMode プロパティにより、SDK ではさまざまな Azure Cosmos DB の宛先エンドポイントに対して一時的なポートの小さなプールを使用できます。
async/await を使用する Task.ResultTask.WaitTask.GetAwaiter().GetResult() のブロック呼び出しを避けます。 コール スタック全体を非同期にして、async/await の組み合わせを有効活用する。 多くの同期的なブロッキング呼び出しを行うと、スレッド プールの枯渇や応答時間の増加が起こります。
エンド ツー エンドのタイムアウト エンドツーエンドのタイムアウトを取得するには、RequestTimeoutCancellationToken の両方のパラメーターを使用する必要があります。 詳細については、 タイムアウトのトラブルシューティング ガイドを参照してください
再試行ロジック 再試行の対象となるエラーと SDK によって再試行されるエラーの詳細については、設計ガイドを参照してください。 複数のリージョンで構成されたアカウントの場合、SDK が他のリージョンで自動的に再試行する シナリオがいくつかあります 。 対して。NET 固有の実装の詳細については、 SDK ソース リポジトリを参照してください。
データベース/コレクション名のキャッシュ 構成からデータベースとコンテナーの名前を取得するか、開始時にそれらをキャッシュします。 ReadDatabaseAsyncReadDocumentCollectionAsyncCreateDatabaseQueryCreateDocumentCollectionQueryなどの呼び出しにより、サービスへのメタデータ呼び出しが発生し、システム予約 RU 制限から消費されます。 また、CreateIfNotExist は、データベースの設定に 1 回だけ使用する必要があります。 一般に、これらの操作は、頻繁に実行しないでください。
一括サポート 待機時間を最適化する必要がない場合は、大量のデータをダンプするための 一括サポート を有効にすることをお勧めします。
並列クエリ Azure Cosmos DB SDK では、クエリの待機時間とスループットを向上させるクエリの並列実行がサポートされています。 MaxConcurrency 内の QueryRequestsOptions プロパティ を、使用しているパーティションの数に設定することをお勧めします。 パーティションの数を認識していない場合は、 int.MaxValueを使用して開始します。最適な待機時間が得られます。 次に、高 CPU 使用率の問題を回避するために、環境のリソース制限に適合するまで数を減らします。 また、MaxBufferedItemCount を、返される結果の予想される数に設定して、プリフェッチされる結果の数を制限します。
パフォーマンス テストのバックオフ アプリケーションでテストを実行する場合は、RetryAfter の間隔でバックオフを実装する必要があります。 バックオフにより、再試行までの待ち時間を最小限に抑えることができます。
インデックス作成 Azure Cosmos DB インデックス作成ポリシーでは、インデックス作成パス (IndexingPolicy.IncludedPathsIndexingPolicy.ExcludedPaths) を使用して、インデックス作成に含めるドキュメント パスまたはインデックス作成から除外するドキュメント パスを指定することもできます。 書き込みを高速化するには、インデックス作成から未使用のパスを除外ししてください。 SDK を使用してインデックスを作成する方法の詳細については、「 インデックス作成ポリシー」を参照してください。
ドキュメント サイズ 特定の操作の要求の料金は、ドキュメントのサイズに直接関係します。 サイズの大きいドキュメントの操作は、サイズの小さいドキュメントの操作よりもコストがかかるので、ドキュメントのサイズを小さくすることをお勧めします。
スレッドまたはタスクの数を増やす Azure Cosmos DB の呼び出しはネットワーク経由で行われるため、クライアント アプリケーションで要求間の待ち時間を最短にするために、要求のコンカレンシーの次数を変えることが必要な場合があります。 たとえば、.NET のタスク並列ライブラリを使用する場合、Azure Cosmos DB に対する読み取りまたは書き込みのタスクを 100 件単位で作成してください。
クエリ メトリックの有効化 バックエンド クエリの実行のログ記録を追加する場合は、.NET SDK を使用して SQL クエリ メトリックを有効にできます。 SQL クエリ メトリックを収集する方法の詳細については、「クエリ メトリックとパフォーマンス」 を参照してください。
SDK のログ記録 例外時や、要求が予想される待機時間を超える場合など、未処理のシナリオの SDK 診断をログします。
デフォルトトレースリスナー この DefaultTraceListener は、高い CPU と I/O のボトルネックを引き起こす運用環境でパフォーマンスの問題を引き起こします。 最新の SDK バージョンを使用していることを確認するか、 アプリケーションから DefaultTraceListener を削除します
識別子で特殊文字を使用しないようにしてください 一部の文字は制限されており、一部の識別子では使用できません: /\?#。 一般的なレコメンデーションは、予期しない動作を回避するために、データベース名、コレクション名、項目 ID、パーティション キーなどの識別子に特殊文字を使用しないことをお勧めします。

診断をキャプチャする

CosmosException を含む SDK のすべての応答には、Diagnostics プロパティがあります。 このプロパティでは、再試行または一時的な失敗があるかどうかなど、1 つの要求に関連するすべての情報が記録されます。

診断は文字列として返されます。 文字列は、さまざまなシナリオのトラブルシューティングに対応するために改良されるので、バージョンによって異なります。 SDK の各バージョンでは、文字列の書式設定に重大な変更が加えられる予定です。 破壊的変更を避けるために、文字列を解析しないでください。 次のコード サンプルは、.NET SDK を使用して診断ログを読み取る方法を示しています。

try
{
    ItemResponse<Book> response = await this.Container.CreateItemAsync<Book>(item: testItem);
    if (response.Diagnostics.GetClientElapsedTime() > ConfigurableSlowRequestTimeSpan)
    {
        // Log the response.Diagnostics.ToString() and add any additional info necessary to correlate to other logs 
    }
}
catch (CosmosException cosmosException)
{
    // Log the full exception including the stack trace with: cosmosException.ToString()
    
    // The Diagnostics can be logged separately if required with: cosmosException.Diagnostics.ToString()
}

// When using Stream APIs
ResponseMessage response = await this.Container.CreateItemStreamAsync(partitionKey, stream);
if (response.Diagnostics.GetClientElapsedTime() > ConfigurableSlowRequestTimeSpan || !response.IsSuccessStatusCode)
{
    // Log the diagnostics and add any additional info necessary to correlate to other logs with: response.Diagnostics.ToString()
}

HTTP 接続のベスト プラクティス

.NET SDK では、構成されている接続モードに関係なく、HttpClient を使用して HTTP 要求を実行します。

  • 直接モードでは、HTTP はメタデータ操作に使用されます
  • ゲートウェイ モードでは、データ プレーン操作とメタデータ操作の両方に HTTP が使用されます

HttpClient の基礎の 1 つは、HttpClientことで、 がアカウントの DNS 変更に対応できるようにすることです。 プールされた接続が開いたままになっている限り、DNS の変更には対応しません。 この設定により、プールされた接続が定期的に閉じられ、アプリケーションが DNS の変更に確実に対応できるようになります。 この値は 、接続モード とワークロードに応じてカスタマイズし、新しい接続を頻繁に作成する場合のパフォーマンス効果と、DNS の変更 (可用性) に対応する必要がある場合のパフォーマンスのバランスを取ることで推奨されます。 5 分の値は、特にゲートウェイ モードの場合、パフォーマンスに影響を与える場合に増やすことができる適切な開始になります。

次のように、CosmosClientOptions.HttpClientFactory を使用してカスタム HttpClient を挿入できます。

// Use a Singleton instance of the SocketsHttpHandler, which you can share across any HttpClient in your application
SocketsHttpHandler socketsHttpHandler = new SocketsHttpHandler();
// Customize this value based on desired DNS refresh timer
socketsHttpHandler.PooledConnectionLifetime = TimeSpan.FromMinutes(5);

CosmosClientOptions cosmosClientOptions = new CosmosClientOptions()
{
    // Pass your customized SocketHttpHandler to be used by the CosmosClient
    // Make sure `disposeHandler` is `false`
    HttpClientFactory = () => new HttpClient(socketsHttpHandler, disposeHandler: false)
};

// Use a Singleton instance of the CosmosClient
return new CosmosClient("<connection-string>", cosmosClientOptions);

.NET 依存関係の挿入を使用する場合は、シングルトン プロセスを簡略化できます。

SocketsHttpHandler socketsHttpHandler = new SocketsHttpHandler();
// Customize this value based on desired DNS refresh timer
socketsHttpHandler.PooledConnectionLifetime = TimeSpan.FromMinutes(5);
// Registering the Singleton SocketsHttpHandler lets you reuse it across any HttpClient in your application
services.AddSingleton<SocketsHttpHandler>(socketsHttpHandler);

// Use a Singleton instance of the CosmosClient
services.AddSingleton<CosmosClient>(serviceProvider =>
{
    SocketsHttpHandler socketsHttpHandler = serviceProvider.GetRequiredService<SocketsHttpHandler>();
    CosmosClientOptions cosmosClientOptions = new CosmosClientOptions()
    {
        HttpClientFactory = () => new HttpClient(socketsHttpHandler, disposeHandler: false)
    };

    return new CosmosClient("<connection-string>", cosmosClientOptions);
});

ゲートウェイ モードを使用する場合のベスト プラクティス

ゲートウェイ モードを使用する場合は、ホストごとに System.Net MaxConnections を増やします。 ゲートウェイ モードを使用すると、Azure Cosmos DB の要求は HTTPS/REST を介して行われます。 それらは、ホスト名または IP アドレスごとの既定の接続数の上限に従います。 場合によっては、Azure Cosmos DB に対する複数の同時接続をクライアント ライブラリで使用できるよう、MaxConnections を高い値 (100 ~ 1,000) に増やす必要があります。 .NET SDK 1.8.0 以降では、ServicePointManager.DefaultConnectionLimit の既定値は 50 です。 値を変更するには、CosmosClientOptions.GatewayModeMaxConnectionLimit を高い値に設定します。

書き込み負荷の高いワークロードのベスト プラクティス

高負荷の作成ペイロードがあるワークロードでは、EnableContentResponseOnWrite 要求オプションを false に設定します。 サービスは、作成または更新されたリソースを SDK に返しません。 通常、アプリケーションには作成済みのオブジェクトがあるため、サービスから返される必要はありません。 ヘッダー値には、まだ要求の料金と同様にアクセスできます。 応答コンテンツを無効にすると、SDK がメモリを割り当てたり応答の本文をシリアル化したりする必要がなくなるため、パフォーマンスを向上させることができます。 また、ネットワーク帯域幅の使用量も削減され、パフォーマンスがさらに向上します。

重要

EnableContentResponseOnWritefalse に設定すると、トリガー操作からの応答も無効になります。

マルチテナント アプリケーションのベスト プラクティス

同じ Azure Cosmos DB アカウント内で、異なるデータベース、コンテナー、またはパーティション キーによって各テナントが表される複数のテナントに使用量を分散するアプリケーションは、1 つのクライアント インスタンスを使用する必要があります。 1 つのクライアント インスタンスは、アカウント内のすべてのデータベース、コンテナー、パーティション キーと対話できます。シングルトン パターンを使用することをお勧めします。

ただし、各テナントが異なる Azure Cosmos DB アカウントによって表されるときは、アカウントごとに別個のクライアント インスタンスを作成する必要があります。 それでもシングルトン パターンは各クライアントに適用されますが (アプリケーションの有効期間中アカウントごとに 1 つのクライアント)、テナントのボリュームが多い場合は、クライアントの数を管理するのが困難になる可能性があります。 接続がコンピューティング環境の限界を超えて増加して、接続の問題を引き起こす可能性があります。

このような場合は、次を行うことをお勧めします。

  • コンピューティング環境 (CPU と接続リソース) の限界を把握します。 可能な限り、少なくとも 4 コアと 8 GB のメモリを備えた VM を使用することをお勧めします。
  • コンピューティング環境の限界に基づいて、1 つのコンピューティング インスタンスで処理できるクライアント インスタンスの数 (つまりテナントの数) を決定します。 選択した接続モードに応じて、クライアントごとに開く接続 の数を見積も ることができます。
  • インスタンス間のテナントの分散を評価します。 各コンピューティング インスタンスが特定の限られた量のテナントを正常に処理できる場合、テナントの負荷分散と異なるコンピューティング インスタンスへのルーティングにより、テナント数の増加に応じてスケーリングが可能になります。
  • スパース ワークロードの場合は、クライアント インスタンスを保持し、時間枠内にアクセスされないテナントのクライアントを破棄する構造として、最も使用頻度の低いキャッシュを使用することを検討してください。 .NET での 1 つの選択肢は MemoryCacheEntryOptions です。これは RegisterPostEvictionCallback を使用して非アクティブなクライアントを破棄し、SetSlidingExpiration を使用して非アクティブな接続を保持する最大時間を定義できます。
  • ゲートウェイ モードを使用して評価し、ネットワーク接続の数を減らします。
  • ダイレクト モードを使用する場合は、Direct モード構成CosmosClientOptions.IdleTcpConnectionTimeoutCosmosClientOptions.PortReuseMode を調整して、未使用の接続を閉じ、接続のボリュームを制御下に保つことを検討してください。

次のステップ

Azure Cosmos DB への移行のための容量計画を実行しようとしていますか? 容量計画のために、既存のデータベース クラスターに関する情報を使用できます。