PAYATHON 2026

Azure REST API 如何获取资源的实时成本?

支付阿杰

结论

Azure 没有通用 REST API,可以按分钟或小时返回“已结算资源成本”。Consumption Usage Details、Cost Management Query 等接口读取的是 Azure 计量和计费管道已经处理的数据,而不是实时计费流。因此,查到的成本通常会延迟数小时,有时甚至超过一天。具体延迟取决于资源类型、计量服务和计费账户类型。

如果业务需要小时级甚至分钟级的数据,需先明确需要哪一类结果:

  • 准确账单成本:使用 Consumption 或 Cost Management API,但必须接受数据延迟。
  • 实时成本概览:从 Azure Monitor 等来源获取实时用量指标,再根据价格、计费规则和折扣自行估算。这类结果只能称为“预估成本”,不能代替最终账单。

仅仅更换成本 endpoint,通常无法解决底层计费数据的延迟问题。

为什么成本数据不是实时的

Azure 资源从运行到生成可查询的成本数据,大致要经过以下过程:

  1. 资源提供程序生成用量记录。
  2. 用量记录进入 Azure 计量系统。
  3. 计费系统应用价格、计费单位、预留实例、Savings Plan、免费额度、折扣和舍入规则。
  4. 处理完成后,成本数据才会出现在 Usage Details 或 Cost Management API 中。

REST API 和 .NET SDK 只是不同的访问方式,读取的是同一类后端计费数据。改用 SDK、REST API 或 Cost Management Query API,都不能让尚未处理的数据提前出现。

另外,“昨天最后一次计费的金额”不一定是固定的 24 小时快照。不同服务的用量记录可能分批到达,历史数据也可能因迟到记录或价格调整而发生变化。

获取准确成本

需要账单口径的数据时,可以继续使用 UsageDetails.ListAsync,也可以通过 Cost Management Query API 按资源、日期或资源组汇总。查询接口更适合生成聚合报表,但数据时效仍受计费管道限制。

例如,通过 Cost Management Query API 按资源汇总成本:

POST https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.CostManagement/query?api-version={supported-api-version}
Authorization: Bearer {access-token}
Content-Type: application/json

{
  "type": "ActualCost",
  "timeframe": "Custom",
  "timePeriod": {
    "from": "2026-08-28T00:00:00Z",
    "to": "2026-08-29T00:00:00Z"
  },
  "dataset": {
    "granularity": "Daily",
    "aggregation": {
      "totalCost": {
        "name": "Cost",
        "function": "Sum"
      }
    },
    "grouping": [
      {
        "type": "Dimension",
        "name": "ResourceId"
      }
    ]
  }
}

api-version 应选用当前 Azure 文档中仍受支持的版本,不要硬编码未经确认的版本号。

即使查询范围包含当天,该接口也只能返回已经进入成本管理系统的数据。尚未处理的小时不会因为被包含在查询范围内而立即出现。

估算小时级或分钟级成本

如果只是为运营看板提供近实时预估,可以采用以下流程:

  1. 从 Azure Monitor Metrics、资源提供程序 API 或应用自身的遥测中获取用量。
  2. 将用量换算成价格表规定的计费单位。
  3. 根据区域、SKU、操作系统、购买方式和币种匹配价格。
  4. 计算基础预估成本。
  5. 定期用 Cost Management 的实际成本回填并修正历史结果。

最简单的线性计费模型是:

EstimatedCost = UsageQuantity × UnitPrice

对于按小时固定收费、且不足一小时按秒计费的资源,可以近似计算:

EstimatedCost = RunningSeconds / 3600 × HourlyPrice

示例 C# 代码:

decimal EstimateComputeCost(
    DateTimeOffset startedAt,
    DateTimeOffset endedAt,
    decimal hourlyPrice)
{
    if (endedAt <= startedAt)
    {
        return 0m;
    }

    decimal runningSeconds =
        (decimal)(endedAt - startedAt).TotalSeconds;

    return runningSeconds / 3600m * hourlyPrice;
}

这个示例只适用于费用与运行时间线性相关,并且 hourlyPrice 已匹配实际 SKU 和购买方式的情况。它不能直接涵盖磁盘、快照、带宽、事务次数、负载均衡规则和软件许可证等附加费用。

不要直接把 VM 开机时间当作完整成本

虚拟机的总成本通常不只有计算实例价格,还可能包括:

TotalEstimatedCost =
    ComputeCost
    + ManagedDiskCost
    + SnapshotCost
    + NetworkEgressCost
    + PublicIPAddressCost
    + LoadBalancerCost
    + SoftwareLicenseCost
    + OtherMeteredServices

以下因素也会导致“用量乘公开单价”的计算结果与最终账单不一致:

  • Enterprise Agreement、Microsoft Customer Agreement 等合同价格
  • 预留实例和 Azure Savings Plan
  • Azure Hybrid Benefit
  • Spot VM 浮动价格
  • 免费额度和赠送额度
  • 阶梯价格、最低计费量和舍入规则
  • 不同区域、币种、SKU 和操作系统
  • 共享资源费用的分摊方式
  • 税费、退款、抵扣和后续账单调整

如果通过 Azure Retail Prices API 获取价格,还需注意,该接口返回的是公开零售价,不一定等于组织最终支付的有效价格。

实际建议

生产系统可以同时维护两条数据链路:

  • 预估链路:使用 Azure Monitor 用量指标和价格模型生成分钟级或小时级看板,并明确标记为“Estimated”。
  • 实际成本链路:使用 Consumption 或 Cost Management API,处理财务报表、预算核对和历史校准。

不要把预估结果标为已结算成本,也不要长期只用 instanceName 关联资源。资源名称可能重复,也可能被重新使用,因此应优先使用完整的 ResourceId 作为资源标识。

获取 Usage quantity 后自行计算,确实是生成近实时成本概览的主要方法,但前提是用量来源本身足够及时。如果 Usage quantity 仍然来自 Consumption API,就会受到同样的计费数据延迟影响。要实现真正的小时级更新,应从 Azure Monitor 或资源自身的运行指标中获取用量。

备注:内容仅供参考。