Azure SDK for C++ は、HTTP パイプライン アーキテクチャを使用して、Azure サービスへの HTTP 要求を処理します。 このドキュメントでは、HTTP パイプラインのしくみ、再試行ポリシーの実装方法、およびアプリケーションのニーズに合わせてカスタマイズする方法について説明します。
HTTP パイプライン アーキテクチャ
HTTP パイプラインとは
HTTP パイプラインは、HTTP 要求と応答を処理するために順番に適用される HTTP ポリシーのスタックです。 Azure SDK 内の各クライアントには、独自の HTTP パイプラインがあります。 パイプライン内のポリシーは、次のような操作を含め、HTTP 要求の処理方法を形成します。
- 認証ヘッダーの追加
- 要求/応答のログ記録
- 失敗した要求の再試行ロジック
- テレメトリの収集
- トランスポート処理 (実際に HTTP 要求を送信)
パイプラインは、次の 2 つの主要な部分に分割されます。
- 呼び出しごとのポリシー - API 操作ごとに 1 回実行
- 再試行ごとのポリシー - 再試行ごとに実行
この構造により、適切なポリシー (認証など) は操作ごとに 1 回だけ実行され、他のポリシー (ログ記録など) は再試行ごとに実行されます。
ポリシーの順序付け
Azure SDK for C++ の一般的な HTTP パイプラインには、次のポリシーが順番に含まれています。
- テレメトリ ポリシー (呼び出しごと) - Azure SDK テレメトリ情報を追加します
- 要求 ID ポリシー (呼び出しごと) - 各要求に一意の ID があることを確認します
- サービス固有の Per-Call ポリシー - サービスに固有のカスタム ポリシー
- 再試行ポリシー (呼び出しごと) - 再試行ロジックを実装します
- サービス固有の Per-Retry ポリシー - 各再試行で実行されるサービスに固有のカスタム ポリシー
- リクエスト アクティビティ ポリシー (各再試行) - 分散トレースを管理します
- ログ ポリシー (再試行ごと) - ログ記録要求と応答を処理します
- トランスポート ポリシー (再試行ごと) - HTTP 要求の実際の送信を処理します
再試行ポリシー
再試行のしくみ
再試行ポリシーは、Azure サービスへの HTTP 要求を行うときに発生する可能性のある一時的なエラーを処理するように設計されています。 一時的なエラーが原因で要求が失敗した場合、再試行ポリシーは次の操作を行います。
- エラーが再試行可能かどうかを判断する
- 適切な遅延を計算する
- その遅延を待つ
- 要求を再試行する
このポリシーでは、トランスポート レベルの障害 (ネットワークの問題) と特定の HTTP 状態コードの両方での再試行がサポートされています。
既定の再試行動作
既定では、再試行ポリシーは次の設定で構成されます。
- 最大 3 回の再試行
- 800 ミリ秒の初期再試行遅延
- 再試行の最大遅延時間 (60 秒)
- 再試行可能な状態コード: 408、429、500、502、503、504
再試行遅延では、ジッターを伴う指数バックオフ戦略が使用されます。
- 最初の再試行: 最大 800 ミリ秒
- 2 回目の再試行: 最大 1,600 ミリ秒
- 3 回目の再試行: 最大 3,200 ミリ秒
- 最大再試行遅延に達するまで繰り返します。
再試行が発生した場合
再試行ポリシーは、次のシナリオで要求の再試行を試みます。
トランスポートエラー:
- ネットワーク接続の問題
- 接続タイムアウト
- DNS (ドメイン ネーム システム) 解決エラー
HTTP 状態コード:
- 408 (タイムアウトの要求)
- 429 (要求が多すぎます)
- 500 (内部サーバー エラー)
- 502 (無効なゲートウェイ)
- 503 (サービスを利用できません)
- 504 (ゲートウェイのタイムアウト)
サービス固有の再試行ロジック:
- Storage などの一部のサービスでは、フェールオーバー シナリオに特化した再試行ロジックが実装されています
再試行動作のカスタマイズ
クライアント オプションの RetryOptions
を変更することで、クライアント作成時の再試行動作をカスタマイズできます。
例: 再試行オプションのカスタマイズ
#include <azure/storage/blobs.hpp>
int main()
{
// Create client options
Azure::Storage::Blobs::BlobClientOptions options;
// Modify retry options
options.Retry.MaxRetries = 5; // Increase max retries
options.Retry.RetryDelay = std::chrono::milliseconds(1000); // Set initial retry delay to 1 second
options.Retry.MaxRetryDelay = std::chrono::seconds(30); // Cap maximum retry delay at 30 seconds
// Add a custom status code to retry on
options.Retry.StatusCodes.insert(Azure::Core::Http::HttpStatusCode::Forbidden); // Retry on 403 errors
// Create the client with custom retry options
auto blobClient = Azure::Storage::Blobs::BlobClient::CreateFromConnectionString(
connectionString,
containerName,
blobName,
options);
// Use the client...
}
カスタム ポリシーの追加
カスタム ポリシーを HTTP パイプラインに追加して、特殊な動作を実装できます。
操作ごとのポリシーの追加
必要な再試行回数に関係なく、操作ごとのポリシーは API 操作ごとに 1 回呼び出されます。
class MyCustomPolicy final : public Azure::Core::Http::Policies::HttpPolicy {
public:
~MyCustomPolicy() override = default;
std::unique_ptr<HttpPolicy> Clone() const override
{
return std::make_unique<MyCustomPolicy>(*this);
}
std::unique_ptr<Azure::Core::Http::RawResponse> Send(
Azure::Core::Http::Request& request,
Azure::Core::Http::Policies::NextHttpPolicy nextPolicy,
Azure::Core::Context const& context) const override
{
// Custom logic before the request
auto response = nextPolicy.Send(request, context);
// Custom logic after the response
return response;
}
};
// Adding the policy to client options
Azure::Storage::Blobs::BlobClientOptions options;
options.PerOperationPolicies.emplace_back(std::make_unique<MyCustomPolicy>());
再試行ごとのポリシーの追加
再試行ごとにポリシーが呼び出されます。
// Similar implementation to above, but add to PerRetryPolicies
options.PerRetryPolicies.emplace_back(std::make_unique<MyCustomRetryPolicy>());
セカンダリ エンドポイントの処理
Storage などの一部の Azure サービスでは、高可用性のためにセカンダリ エンドポイントがサポートされています。 SDK には、セカンダリ エンドポイントへの自動フェールオーバーのサポートが含まれています。
Azure::Storage::Blobs::BlobClientOptions options;
// Configure secondary endpoint for Storage
std::string primaryUrl = blobClient.GetUrl();
std::string secondaryUrl = InferSecondaryUrl(primaryUrl); // Your logic to determine secondary URL
std::string secondaryHost = Azure::Core::Url(secondaryUrl).GetHost();
options.SecondaryHostForRetryReads = secondaryHost;
再試行のログ記録
HTTP パイプラインには、再試行のための組み込みのログ記録が含まれています。 再試行に関する情報を表示するようにログ 記録レベルを構成できます。
// Set log level to see retry information
Azure::Core::Diagnostics::Logger::SetLevel(Azure::Core::Diagnostics::Logger::Level::Informational);
// Set a custom log listener to capture logs
Azure::Core::Diagnostics::Logger::SetListener([](auto level, auto message) {
std::cout << "Log [" << static_cast<int>(level) << "]: " << message << std::endl;
});
再試行が発生すると、ログ エントリは次のように表示されます。
- "HTTP トランスポート エラー: [エラーの詳細]"
- "HTTP 再試行の試行 #1 は 800 ミリ秒で行われます。"
- "HTTP 状態コード 503 が再試行されます。"
ベスト プラクティス
可能な場合は既定の再試行設定を使用する
- 既定の設定はほとんどのシナリオに合わせて調整され、指数バックオフなどのベスト プラクティスが含まれています
非べき等な操作には注意してください
- 再試行が安全でない操作 (非idempotent POST 要求など) の再試行を制限することを検討してください
サーキットブレーカーパターンを検討する
- 大量のアプリケーションの場合は、サーキット ブレーカー パターンを実装して、エラーで応答するサービスが圧倒的に多くなるのを防ぎます
再試行のシナリオをテストする
- 再試行が発生したときのアプリケーションの動作をテストして、適切な処理を確認する
再試行テレメトリを監視する
- 再試行率が高い場合は、対処する必要がある根本的な問題を示している可能性があります
高度なパイプラインの内部構造
HTTP パイプラインは、ポリシー実行のシーケンスを管理する Azure::Core::Http::_internal::HttpPipeline
クラスに実装されます。 要求が行われると、パイプラインは次のようになります。
- パイプラインの最初のポリシーから開始します
- 各ポリシーは要求を処理し、次のポリシーに渡します
- 最後のポリシーは通常、トランスポート ポリシーであり、実際に要求を送信します。
- その後、応答は逆の順序でポリシーを通過します。
再試行ポリシーは、パイプライン内でその後に来るポリシーのシーケンス全体を繰り返すことができるという点で特別です。
トラブルシューティング
再試行に関する問題が発生している場合:
情報ログを有効にする
-
AZURE_LOG_LEVEL
環境変数をInformational
に設定して再試行を確認する
-
トランスポート エラーを確認する
- 多くの場合、ネットワークの問題はトランスポート例外として現れます
サービスの正常性を確認する
- 永続的な 500 レベルのエラーは、Azure サービスの問題を示している可能性があります
要求 ID を確認する
- 各要求には、Azure サポートを使用するときに使用できる一意の ID があります
タイムアウト設定を確認する
- アプリケーションのタイムアウトが再試行ポリシーと互換性があることを確認する