如何按 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 分析使用情况并进行内部成本分摊。
备注:内容仅供参考。
