次の方法で共有


Azure SDK for C++ での HTTP パイプラインと再試行

Azure SDK for C++ は、HTTP パイプライン アーキテクチャを使用して、Azure サービスへの HTTP 要求を処理します。 このドキュメントでは、HTTP パイプラインのしくみ、再試行ポリシーの実装方法、およびアプリケーションのニーズに合わせてカスタマイズする方法について説明します。

HTTP パイプライン アーキテクチャ

HTTP パイプラインとは

HTTP パイプラインは、HTTP 要求と応答を処理するために順番に適用される HTTP ポリシーのスタックです。 Azure SDK 内の各クライアントには、独自の HTTP パイプラインがあります。 パイプライン内のポリシーは、次のような操作を含め、HTTP 要求の処理方法を形成します。

  • 認証ヘッダーの追加
  • 要求/応答のログ記録
  • 失敗した要求の再試行ロジック
  • テレメトリの収集
  • トランスポート処理 (実際に HTTP 要求を送信)

パイプラインは、次の 2 つの主要な部分に分割されます。

  1. 呼び出しごとのポリシー - API 操作ごとに 1 回実行
  2. 再試行ごとのポリシー - 再試行ごとに実行

この構造により、適切なポリシー (認証など) は操作ごとに 1 回だけ実行され、他のポリシー (ログ記録など) は再試行ごとに実行されます。

ポリシーの順序付け

Azure SDK for C++ の一般的な HTTP パイプラインには、次のポリシーが順番に含まれています。

  1. テレメトリ ポリシー (呼び出しごと) - Azure SDK テレメトリ情報を追加します
  2. 要求 ID ポリシー (呼び出しごと) - 各要求に一意の ID があることを確認します
  3. サービス固有の Per-Call ポリシー - サービスに固有のカスタム ポリシー
  4. 再試行ポリシー (呼び出しごと) - 再試行ロジックを実装します
  5. サービス固有の Per-Retry ポリシー - 各再試行で実行されるサービスに固有のカスタム ポリシー
  6. リクエスト アクティビティ ポリシー (各再試行) - 分散トレースを管理します
  7. ログ ポリシー (再試行ごと) - ログ記録要求と応答を処理します
  8. トランスポート ポリシー (再試行ごと) - HTTP 要求の実際の送信を処理します

Azure SDK for C++ HTTP パイプラインのポリシー フェーズを示す図。

再試行ポリシー

再試行のしくみ

再試行ポリシーは、Azure サービスへの HTTP 要求を行うときに発生する可能性のある一時的なエラーを処理するように設計されています。 一時的なエラーが原因で要求が失敗した場合、再試行ポリシーは次の操作を行います。

  1. エラーが再試行可能かどうかを判断する
  2. 適切な遅延を計算する
  3. その遅延を待つ
  4. 要求を再試行する

このポリシーでは、トランスポート レベルの障害 (ネットワークの問題) と特定の HTTP 状態コードの両方での再試行がサポートされています。

既定の再試行動作

既定では、再試行ポリシーは次の設定で構成されます。

  • 最大 3 回の再試行
  • 800 ミリ秒の初期再試行遅延
  • 再試行の最大遅延時間 (60 秒)
  • 再試行可能な状態コード: 408、429、500、502、503、504

再試行遅延では、ジッターを伴う指数バックオフ戦略が使用されます。

  • 最初の再試行: 最大 800 ミリ秒
  • 2 回目の再試行: 最大 1,600 ミリ秒
  • 3 回目の再試行: 最大 3,200 ミリ秒
  • 最大再試行遅延に達するまで繰り返します。

再試行が発生した場合

再試行ポリシーは、次のシナリオで要求の再試行を試みます。

  1. トランスポートエラー:

    • ネットワーク接続の問題
    • 接続タイムアウト
    • DNS (ドメイン ネーム システム) 解決エラー
  2. HTTP 状態コード:

    • 408 (タイムアウトの要求)
    • 429 (要求が多すぎます)
    • 500 (内部サーバー エラー)
    • 502 (無効なゲートウェイ)
    • 503 (サービスを利用できません)
    • 504 (ゲートウェイのタイムアウト)
  3. サービス固有の再試行ロジック:

    • 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 が再試行されます。"

ベスト プラクティス

  1. 可能な場合は既定の再試行設定を使用する

    • 既定の設定はほとんどのシナリオに合わせて調整され、指数バックオフなどのベスト プラクティスが含まれています
  2. 非べき等な操作には注意してください

    • 再試行が安全でない操作 (非idempotent POST 要求など) の再試行を制限することを検討してください
  3. サーキットブレーカーパターンを検討する

    • 大量のアプリケーションの場合は、サーキット ブレーカー パターンを実装して、エラーで応答するサービスが圧倒的に多くなるのを防ぎます
  4. 再試行のシナリオをテストする

    • 再試行が発生したときのアプリケーションの動作をテストして、適切な処理を確認する
  5. 再試行テレメトリを監視する

    • 再試行率が高い場合は、対処する必要がある根本的な問題を示している可能性があります

高度なパイプラインの内部構造

HTTP パイプラインは、ポリシー実行のシーケンスを管理する Azure::Core::Http::_internal::HttpPipeline クラスに実装されます。 要求が行われると、パイプラインは次のようになります。

  1. パイプラインの最初のポリシーから開始します
  2. 各ポリシーは要求を処理し、次のポリシーに渡します
  3. 最後のポリシーは通常、トランスポート ポリシーであり、実際に要求を送信します。
  4. その後、応答は逆の順序でポリシーを通過します。

再試行ポリシーは、パイプライン内でその後に来るポリシーのシーケンス全体を繰り返すことができるという点で特別です。

トラブルシューティング

再試行に関する問題が発生している場合:

  1. 情報ログを有効にする

    • AZURE_LOG_LEVEL環境変数をInformationalに設定して再試行を確認する
  2. トランスポート エラーを確認する

    • 多くの場合、ネットワークの問題はトランスポート例外として現れます
  3. サービスの正常性を確認する

    • 永続的な 500 レベルのエラーは、Azure サービスの問題を示している可能性があります
  4. 要求 ID を確認する

    • 各要求には、Azure サポートを使用するときに使用できる一意の ID があります
  5. タイムアウト設定を確認する

    • アプリケーションのタイムアウトが再試行ポリシーと互換性があることを確認する