共用方式為

使用片段执行策略

适用于:所有 API 管理层级

在整个请求和响应生命周期中具有自定义行为的高级管道方案是使用策略片段生成的。 产品和 API 级别的中心策略使用 include-fragment 策略插入片段。 可以在 产品和 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 客户端可见。 创建一个专用标头管理片段,用于合并一个位置中的所有调试标头,而不是在整个片段中添加单个调试标头。 这种集中式方法可确保一致性并提高可维护性。

<!-- 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 管理 API 进行身份验证以获取访问令牌
  2. 获取调试凭据以获取调试跟踪令牌
  3. 使用调试令牌发送带有跟踪的请求
  4. 检索显示执行流和策略详细信息的完整跟踪输出

跟踪输出包含有关片段执行顺序、变量状态和策略处理的详细信息,可帮助识别管道中的问题。 有关详细信息,请参阅 为 API 启用跟踪

为了帮助排查管道问题,请复制完整的跟踪输出,并将其提供给 GitHub Copilot,以获取有关解决问题的详细分析和建议。