PAYATHON 2026

如何按 Products 监控 Azure API Management 成本与计费?

支付老李

结论

不能通过 APIM 的 Product 获得 Azure 官方提供的独立成本和账单。

Azure Cost Management 通常根据 APIM 资源实例、SKU、容量单位、区域及相关资源计费,不会把同一个 APIM 实例的费用拆分到各个 Product。将 test 和 production 放在同一个 APIM 实例中后,可以按 Product 统计请求量、流量、延迟、错误率和订阅使用情况,但这些数据属于使用分析,并非 Azure Billing 提供的实际费用明细。

可以根据具体目标选择方案:

  • 如果希望开发人员只注册一次,可以合并为一个 APIM 实例,并创建 test 和 production 两个 Product。
  • 如果需要分别统计两个环境的使用情况,可以通过 Azure Monitor、Log Analytics 或 Application Insights 按 ProductId 汇总。
  • 如果需要严格、可审计的独立账单,应继续使用独立的 APIM 资源。另一种做法是按使用量在内部进行成本分摊,但不能把分摊结果视为 Azure 官方账单。

推荐的整合方式

可以在同一个 APIM 实例中分别定义两个环境的资源:

APIM instance
├── Product: test
│   ├── API: orders-test
│   └── Backend: test backend
└── Product: production
    ├── API: orders-production
    └── Backend: production backend

开发人员只需在同一个 developer portal 中注册账户,再分别申请两个 Product 的订阅权限。每个 Product 都可以单独设置自动批准或管理员审核。

Product 主要用于组织 API、控制可见性和管理订阅。它不会隔离后端,也不会自动把请求发送到不同环境。因此,test 和 production 应使用不同的 API、路径、后端配置或策略,例如:

https://api.example.com/test/orders
https://api.example.com/production/orders

也可以为两个环境使用不同的自定义域名,具体方式取决于 APIM 层级和域名配置。

按 Product 统计使用情况

先为 APIM 启用诊断日志,并将网关日志发送到 Log Analytics。使用资源专用日志表时,可以按 ProductId 汇总请求:

ApiManagementGatewayLogs
| where TimeGenerated >= startofday(ago(30d))
| summarize
    Requests = count(),
    FailedRequests = countif(ResponseCode >= 400),
    AverageDurationMs = avg(TotalTime),
    TotalResponseBytes = sum(ResponseSize)
    by ProductId
| order by Requests desc

也可以按天查看变化趋势:

ApiManagementGatewayLogs
| where TimeGenerated >= ago(30d)
| summarize
    Requests = count(),
    FailedRequests = countif(ResponseCode >= 400)
    by ProductId, bin(TimeGenerated, 1d)
| order by TimeGenerated asc

日志表名和字段取决于诊断设置、日志模式及工作区配置。如果环境仍在使用旧版 AzureDiagnostics 表,应先检查实际字段,再修改查询,不要直接套用相同的字段名称。

记录额外的环境维度

如果现有日志无法稳定区分环境,可以在 Product 或 API 作用域添加 trace 策略,将 Product 和 API 信息写入已经配置的遥测目标:

<policies>
    <inbound>
        <base />
        <trace source="environment-usage" severity="information">
            <message>@("APIM request received")</message>
            <metadata name="productId"
                      value="@(context.Product?.Id ?? "none")" />
            <metadata name="apiId"
                      value="@(context.Api?.Id ?? "none")" />
            <metadata name="subscriptionId"
                      value="@(context.Subscription?.Id ?? "none")" />
        </trace>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

只有启用了对应的诊断设置和遥测目标,trace 才会生成可查询的数据。记录日志时,还要避免写入订阅密钥、Authorization Header、请求正文中的个人信息及其他敏感数据。

如何进行内部成本分摊

Azure Cost Management 可以提供整个 APIM 实例的实际成本。在此基础上,可以根据各 Product 的使用统计进行内部估算。例如,按请求数分摊:

[ C_p = C_{\text{APIM}} \times \frac{R_p}{\sum_i R_i} ]

其中:

  • (C_p):某个 Product 的估算成本
  • (C_{\text{APIM}}):该 APIM 实例在统计周期内的实际成本
  • (R_p):该 Product 的请求数

假设 APIM 每月成本为 10,000 元,production 占请求量的 80%,test 占 20%,内部可分摊为:

production: 8,000 元
test:       2,000 元

按请求量分摊比较简单,但未必公平,因为不同请求的处理时间、响应大小、缓存命中率和外部网络流量可能不同。需要更精细的模型时,可以使用加权请求量:

[ W_p = \alpha R_p + \beta T_p + \gamma B_p ]

其中 (T_p) 是处理时间,(B_p) 是传输量,权重由组织根据实际成本结构制定。无论使用哪种算法,计算结果都只是内部 chargeback/showback 数据,不是 Azure 出具的 Product 级账单。

后端成本需要单独统计

APIM Product 只能帮助识别经过网关的调用,无法自动归集以下资源的费用:

  • App Service
  • Azure Functions
  • AKS
  • Container Apps
  • 数据库和存储
  • Application Insights 和 Log Analytics
  • 跨区域或公网数据传输

如果 test 和 production 的后端仍位于不同 subscription,可以直接在 Azure Cost Management 中按 subscription、resource group 或 tag 查看实际成本。建议为相关资源设置统一标签,例如:

environment = test
environment = production
service     = orders
costCenter  = engineering

合并 APIM 后,网关费用只能依据使用统计进行分摊,后端费用仍可按各自的 subscription 或 tag 统计。

合并前需要考虑的风险

把两个环境放入同一个 APIM 实例可以简化开发人员注册流程,但也会降低隔离程度:

  • test 流量可能占用 production 的共享容量。
  • 配置错误或实例故障可能同时影响两个环境。
  • 两个环境需要共同管理扩容、升级、网络和证书配置。
  • test 与 production 会共享同一个 APIM 资源的管理边界。
  • 如果同一个 API 被加入多个 Product,必须明确请求使用哪个订阅,否则统计归属可能不符合预期。
  • 不要求订阅的 API 可能缺少用于确定 Product 归属的订阅上下文。

如果主要问题只是开发人员需要注册两次,可以考虑保留两个 APIM 实例,再通过统一身份认证、自动化用户授权或订阅流程改善使用体验。如果能够接受共享容量和共享故障域,也可以合并实例,按 Product 分析使用情况并进行内部成本分摊。

备注:内容仅供参考。