次の方法で共有


ポリシー フラグメントの変数管理

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

コンテキスト変数 を使用すると、高度なパイプライン シナリオでポリシー フラグメント間でデータを共有できます。 最適なパフォーマンスで信頼性の高いパイプラインを構築するためには、適切な変数管理が不可欠です。 不適切な処理は、実行時エラー、パフォーマンスの問題、および予期しない動作につながる可能性があります。

変数の基礎

コンテキスト変数は、ポリシー フラグメント間でスレッド セーフなデータ共有を提供し、組み込みの セット変数 ポリシーを使用して作成されます。 各要求は、独自の分離された変数コンテキストを維持し、同時要求が相互に干渉しないようにします。

変数ライフサイクル管理

  • 要求スコープ: 変数は 1 つの要求中にのみ存在し、要求が完了すると自動的にガベージ コレクションされます。

  • フェーズの永続化: 受信フェーズで設定された変数は、同じ要求内のバックエンド、送信、およびエラー フェーズ全体で使用できます。

  • スレッドの分離: 厳密なスレッド分離により、各要求は独自のコンテキスト オブジェクトを使用して独自のスレッドで実行され、要求間のデータ干渉を防ぐことができます。

  • 順次更新: フラグメントは既存の変数を変更でき、後続のフラグメントは以前の値を上書きします。 順次実行すると、ロック メカニズムが不要になります。

  • ストレージのしきい値: プラットフォームは、小さなコレクション (通常は要求あたり 50 個以下) のコンテキスト変数管理を最適化します。

フラグメント内の変数の設定と取得

<!-- Example: Set a request-id context variable that is a required value for other fragments -->
<set-variable name="request-id" value="@{
    var requestId = context.Request.Headers.GetValueOrDefault("X-Request-ID", "");
    if (string.IsNullOrEmpty(requestId)) {
        return Guid.NewGuid().ToString();
    }
    return requestId;
}" />

<!-- Example: Retrieve the same request-id context variable safely in another fragment -->
<set-header name="X-Correlation-ID" value="@{
    return context.Variables.GetValueOrDefault<string>("request-id", "unknown");
}" />

ベスト プラクティス

安全な変数アクセスを使用する

常に潜在的な null 値に注意し、 GetValueOrDefaultで安全なアクセスを使用し、すべての変数アクセスに意味のある既定値を指定します。

<!-- Safe access with default value -->
<set-variable name="log-level" value="@{
    return context.Variables.GetValueOrDefault<string>("config-log-level", "INFO");
}" />

<!-- Safe string interpolation using GetValueOrDefault -->
<set-variable name="cache-key" value="@{
    var userId = context.Variables.GetValueOrDefault<string>("auth-user-id", "anon");
    var resource = context.Variables.GetValueOrDefault<string>("request-resource", "default");
    
    return $"cache:{userId}:{resource}";
}" />

変数の存在を確認する

前提条件フラグメントによって作成された変数にアクセスする前に、変数が存在することを確認します。 依存関係がない場合は、次の 2 つの方法から選択します。

戦略 1: 高速失敗 (重要な依存関係)

重要な依存関係がない場合は、エラー応答を返します。

<choose>
    <when condition="@(!context.Variables.ContainsKey("user-id"))">
        <!-- Critical dependency missing - fail immediately -->
        <return-response>
            <set-status code="500" reason="Internal Server Error" />
            <set-body>{"error": "Required variable missing", "missing_dependency": "user-id"}</set-body>
        </return-response>
    </when>
    <otherwise>
        <!-- Safe to proceed - use the user-id variable -->
        <set-header name="X-User-ID" exists-action="override">
            <value>@(context.Variables.GetValueOrDefault<string>("user-id", ""))</value>
        </set-header>
    </otherwise>
</choose>

戦略 2: 適切に処理する (オプションの依存関係)

省略可能な依存関係がない場合は、適切なフォールバック動作で実行を続行します。

<choose>
    <when condition="@(context.Variables.ContainsKey("user-id"))">
        <!-- Optional variable available - use it -->
        <set-header name="X-User-ID" exists-action="override">
            <value>@(context.Variables.GetValueOrDefault<string>("user-id", ""))</value>
        </set-header>
    </when>
    <otherwise>
        <!-- Fallback to default when variable unavailable -->
        <set-header name="X-User-ID" exists-action="override">
            <value>unknown</value>
        </set-header>
    </otherwise>
</choose>

変数アクセスを最小限に抑える

複数のアクセスを 1 つの式に統合することで、コンテキスト変数の参照を減らします。

<!-- Good: Single consolidated access -->
<set-variable name="log-entry" value="@{
    var level = context.Variables.GetValueOrDefault<string>("log-level", "INFO");
    var requestId = context.Variables.GetValueOrDefault<string>("request-id", "unknown");
    return $"[{level}] Request {requestId} completed";
}" />

<!-- Avoid: Multiple separate accesses -->
<set-variable name="level-prefix" value="@("[" + context.Variables.GetValueOrDefault<string>("log-level", "INFO") + "]")" />
<set-variable name="request-suffix" value="@("Request " + context.Variables.GetValueOrDefault<string>("request-id", "unknown") + " completed")" />
<set-variable name="log-entry" value="@(context.Variables.GetValueOrDefault<string>("level-prefix", "") + " " + context.Variables.GetValueOrDefault<string>("request-suffix", ""))" />

一貫性のある型を維持する

パフォーマンスと信頼性を最適化するために、明示的な型処理を使用します。 ポリシー式を使用する場合は、@()演算子で想定される型を指定します。

<!-- Set as boolean, use as boolean -->
<set-variable name="should-log-debug" value="@(true)" />
<choose>
    <when condition="@(context.Variables.GetValueOrDefault<bool>("should-log-debug", false))">
        <!-- Include detailed debug information in logs -->
    </when>
</choose>