次の方法で共有


フラグメントを使用したポリシーの実行

適用対象: すべての API Management レベル

要求と応答のライフサイクル全体にわたってカスタム動作を持つ高度なパイプライン シナリオは、ポリシー フラグメントを使用して構築されます。 製品レベルと API レベルの中央ポリシーでは、 インクルード フラグメント ポリシーを使用してフラグメントが挿入されます。 製品ポリシーと API ポリシー間でフラグメントを共有して、責任を明確に分離しながら、重複を回避できます。

フラグメント挿入

中央ポリシーを使用してフラグメントを挿入する

製品および API ポリシー定義は、要求と応答の完全なパイプラインを作成するために特定の順序でフラグメントを挿入するオーケストレーターとして機能します。 次の例は、ポリシー定義によって挿入されたフラグメントを示しています。

<policies>
  <inbound>
    <include-fragment fragment-id="security-context" />
    <include-fragment fragment-id="rate-limiting" />
    <include-fragment fragment-id="request-logging" />
    <base />
  </inbound>
  <backend>
    <include-fragment fragment-id="backend-selection" />
    <base />
  </backend>
  <outbound>
    <include-fragment fragment-id="circuit-breaker" />
    <base />
  </outbound>
  <on-error>
    <include-fragment fragment-id="error-response" />
  </on-error>
</policies>

主な概念

  • 順次: フラグメントは、含まれている順序で実行されます。
  • フェーズの配置: フラグメントは、機能に基づいて適切なポリシー フェーズ (受信、バックエンド、送信、エラー時) に挿入されます。
  • 依存関係管理: 後のフラグメントは、シーケンス内の以前のフラグメントによって設定されたコンテキスト変数に依存できます。

ベスト プラクティス

スコープに基づいてフラグメントを挿入する

製品ポリシーと API ポリシーが、 スコープに応じてフラグメントの責任を分割することによって効果的に連携することを確認します。

  • 製品ポリシー: 製品ごとに異なる製品固有の動作を実行するフラグメントを挿入します。
  • API ポリシー: すべての製品に適用されるフラグメントを挿入します。

重複を回避するためにフラグメントを再利用する

同じフラグメントを再利用して、製品ポリシーと API ポリシー間で同じロジックが必要な場合に重複を排除します。 この例では、 circuit-breaker フラグメントが再利用されます。

<!-- Product Policy -->
<policies>
  <inbound>
    <include-fragment fragment-id="security-context" />
    <include-fragment fragment-id="rate-limiting" />
    <base />
  </inbound>
  <backend>
    <include-fragment fragment-id="backend-selection" />
    <base />
  </backend>
  <outbound>
    <include-fragment fragment-id="circuit-breaker" />
    <base />
  </outbound>
</policies>
<!-- API Policy -->
<policies>
  <inbound>
    <include-fragment fragment-id="request-logging" />
    <base />
  </inbound>
  <outbound>
    <include-fragment fragment-id="circuit-breaker" />
    <base />
  </outbound>
</policies>

フラグメントの依存関係とデータ コントラクトを文書化する

必要なフラグメントと変数を明確にするために、各フラグメントの依存関係とデータ コントラクトを文書化します。 コメントを使用して以下を指定します。

  • 依存関係: このフラグメントの前に実行する必要があるその他のフラグメント
  • 必須: このフラグメントを実行する前に存在する必要があるコンテキスト変数
  • 生成: このフラグメントがダウンストリーム フラグメント用に生成するコンテキスト変数
<fragment fragment-id="rate-limiting-fragment">
  <!-- Dependencies: security-context-fragment, config-cache-fragment -->
  <!-- Requires: subscription-key variables -->
  <!-- Produces: rate-limit-applied, rate-limit-remaining variables -->
  
  <!-- Verify dependencies before execution -->
  <choose>
    <when condition="@(!context.Variables.ContainsKey("subscription-key"))">
      <return-response>
        <set-status code="500" reason="Internal Server Error" />
        <set-body>Rate limiting requires security context</set-body>
      </return-response>
    </when>
  </choose>
  
  <!-- Rate limiting logic -->
  <set-variable name="rate-limit-applied" value="@(true)" />
  <set-variable name="rate-limit-remaining" value="@(95)" />
</fragment>

条件付きフラグメント包含を使用する

要求の特性、構成設定、またはランタイム コンテキストに基づいてフラグメントを動的に含める条件付きロジックを中央ポリシー内に実装します。 このパターンにより、さまざまなシナリオに適応する柔軟な処理パイプラインが可能になります。

<!-- Product Policy -->
<policies>
  <inbound>
    <include-fragment fragment-id="config-cache" />
    <include-fragment fragment-id="request-analysis" />
    
    <!-- Conditional authentication with custom logic based on request type -->
    <choose>
      <when condition="@(context.Request.Headers.GetValueOrDefault("Authorization", "").StartsWith("Bearer"))">
        <include-fragment fragment-id="security-jwt" />
      </when>
      <otherwise>
        <include-fragment fragment-id="security-api-key" />
      </otherwise>
    </choose>
    
    <base />
  </inbound>
</policies>

フラグメント間で要求本文を保持する

フラグメントが処理のために要求本文 (メタデータの抽出や検証など) を読み取る必要がある場合は、常に preserveContent: true を使用して、ダウンストリーム フラグメントとバックエンド転送で要求本文を引き続き使用できるようにします。

<set-variable name="request-metadata" value="@{
  try {
    // CRITICAL: preserveContent: true ensures body remains available for other fragments and backend
    var body = context.Request.Body.As<string>(preserveContent: true);
    var requestData = JObject.Parse(body);
    
    // Extract metadata without consuming the body
    return new JObject {
      ["user-id"] = requestData["user"]?.ToString() ?? "anonymous"
    };
  } catch {
    return new JObject();
  }
}" />

preserveContent: true がない場合、要求本文を読み取ると消費され、そのあとのフラグメントやバックエンドサービスでは利用できなくなります。

テストとデバッグ

フラグメント パイプラインの効果的なデバッグには、実行フローと変数の状態を理解するための体系的なアプローチが必要です。 このセクションでは、要求処理の可視性を最大化しながら、パフォーマンスへの影響を最小限に抑えるデバッグアプローチを示します。

デバッグ ヘッダーを有効にする

デバッグ ヘッダーを使用して、問題のトラブルシューティングのためにパイプライン内の特定の時点で変数の状態をキャプチャします。 デバッグ ヘッダーは HTTP 応答ヘッダーに表示され、API クライアントに表示されます。 フラグメント全体に個別のデバッグ ヘッダーを追加する代わりに、すべてのデバッグ ヘッダーを 1 つの場所に統合する専用のヘッダー管理フラグメントを作成します。 この一元化されたアプローチにより、一貫性が確保され、保守容易性が向上します。

<!-- Example: Dedicated header fragment -->
<fragment fragment-id="debug-headers">
  <!-- Debug headers for troubleshooting -->
  <set-header name="X-Debug-Request-Type" exists-action="override">
    <value>@(context.Variables.GetValueOrDefault<string>("request-type", "unknown"))</value>
  </set-header>
  <set-header name="X-Debug-Selected-Backend" exists-action="override">
    <value>@(context.Variables.GetValueOrDefault<string>("selected-backend", "unknown"))</value>
  </set-header>
  <set-header name="X-Debug-Request-ID" exists-action="override">
    <value>@(context.Variables.GetValueOrDefault<string>("request-id", "unknown"))</value>
  </set-header>
</fragment>

パイプラインの配置:

他のすべてのフラグメントの実行が完了した後、製品ポリシーの 送信 セクションにヘッダー管理フラグメントを含めます。

<policies>
  <outbound>
    <include-fragment fragment-id="circuit-breaker" />
    <include-fragment fragment-id="resource-tracking" />
    <!-- Headers fragment - placed last to capture final state -->
    <include-fragment fragment-id="debug-headers" />
    <base />
  </outbound>
</policies>

代替 - インライン デバッグ ヘッダー:

単純なシナリオや個々のフラグメントをテストする場合は、デバッグ ヘッダーを直接追加できます。

<set-header name="X-Debug-Variables" exists-action="override">
    <value>@{
        var debug = new JObject();
        debug["request-id"] = context.Variables.GetValueOrDefault<string>("request-id", "not-set");
        debug["request-type"] = context.Variables.GetValueOrDefault<string>("request-type", "not-set");
        debug["selected-backend"] = context.Variables.GetValueOrDefault<string>("selected-backend", "not-set");
        return debug.ToString(Formatting.None);
    }</value>
</set-header>

フラグメントの実行をトレースする

実行のパンくずリストを作成し、フラグメントのシーケンスを検証して、製品とAPIポリシーの境界を越えて実行されるフラグメントを特定します。 この手法は、条件付きロジックをデバッグし、特定のフラグメントがスキップされた理由を理解するために不可欠です。 次のコードを各フラグメントの先頭に追加し、"fragment-name" を実際のフラグメント名に置き換えます。

<set-variable name="execution-trace" value="@{
    var trace = context.Variables.GetValueOrDefault<string>("execution-trace", "");
    return trace + "→fragment-name";
}" />

パンくずリストを表示するには、組み込みの トレース ポリシーを使用して実行フローをログに記録します。

<trace source="Fragment-Execution" severity="information">
    <message>@(context.Variables.GetValueOrDefault<string>("execution-trace", ""))</message>
</trace>

要求トレースを使用したデバッグ

要求トレースを有効にして、予期しない動作をトラブルシューティングするために、ポリシー パイプラインを介して詳細な実行トレースをキャプチャします。 要求トレースを有効にするには、クライアントで次の操作を行う必要があります。

  1. API Management Management API を使用して認証し、アクセス トークンを取得する
  2. デバッグ資格情報を取得してデバッグ トレース トークンを取得する
  3. デバッグ トークンを使用してトレースを有効にして要求を送信する
  4. 実行フローとポリシーの詳細を示す完全なトレース出力を取得する

トレース出力には、パイプラインの問題を特定するのに役立つフラグメント実行順序、変数の状態、およびポリシー処理に関する詳細情報が含まれています。 詳細については、「API の トレースを有効にする」を参照してください。

パイプラインの問題のトラブルシューティングを支援するには、完全なトレース出力をコピーし、GitHub Copilot に提供して、問題の解決に関する詳細な分析と推奨事項を提供します。