PAYATHON 2026

Google Places 出现 API 每日配额错误

数据小许

结论

Premium plan web service requests per day: unlimited 只表示对应项目和服务的每日总量配额没有固定上限,不代表所有 Google Places 请求都不受限制。

如果 IAM & Admin 的 Quotas 页面显示 current usage 100%: 1,通常是实际请求命中了上限为 1 的配额指标,或者生产环境使用的 API key、Cloud 项目和控制台当前查看的项目并不一致。其他可能原因还包括 Places API 未启用、API key 限制配置错误、结算账号未真正绑定到请求所属项目,或短周期速率配额已经耗尽。

排查时不能只看 billing 是否显示有效。需要确认每次失败请求实际使用了哪个项目、哪个凭据和哪个 API,以及具体触发了哪项配额限制。

为什么 unlimited 仍会报配额错误

Google Maps Platform 同时使用多种配额和配置限制,包括:

  • 每日请求配额
  • 每分钟请求数
  • 每分钟每用户请求数
  • 特定 Places 服务的独立配额
  • 手动设置的 quota override
  • API key 所属项目的结算和 API 启用状态
  • Premium Plan 旧凭据与普通 API key 对应的不同计费路径

任何一项实际生效的配额达到上限,都可能导致请求返回 OVER_QUERY_LIMIT,或出现类似提示:

You have exceeded your daily request quota for this API.

控制台中的 current usage 100%: 1 需要重点检查。它可能表示该指标的有效上限就是 1,而不是已经使用了一个所谓的无限配额。常见原因是误设了每日上限、配额调整没有应用到正确项目,或者当前查看的项目与生产 API key 所属项目不同。

部分 Google Maps API 会用相近的错误状态表示不同的配置问题。因此,即使错误文案提到每日配额,也不能据此断定请求量过大就是唯一原因。

排查步骤

1. 确认生产环境实际使用的凭据

不要只检查浏览器或服务器配置文件中原本打算使用的 key,要直接查看失败请求实际携带的凭据。

浏览器端可以在开发者工具的 Network 面板中检查 Maps JavaScript API 的加载地址,例如:

https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places

服务端 Web Service 请求可能类似:

https://maps.googleapis.com/maps/api/place/details/json?place_id=PLACE_ID&key=YOUR_API_KEY

检查生产环境是否仍在使用旧 key、测试项目的 key 或已经撤销的 key,也要确认环境变量加载失败时是否会回退到其他凭据。

API key 属于敏感凭据。排查期间不要把完整 key 写入日志或公开工单,最多保留脱敏后的前后几位。

2. 根据 API key 找到所属项目

在 Google Cloud Console 的 Credentials 页面找到该 key,并逐项确认:

  • key 所属的 Cloud 项目
  • 该项目是否就是当前查看 Quotas 的项目
  • billing account 是否已绑定到该项目
  • billing account 是否处于可计费状态
  • 生产请求所需的 Places API 是否已在该项目启用

结算账号本身有效,不等于当前项目已经正确关联该账号,这两项需要分别核对。

如果使用 Maps JavaScript API 的 Places Library,需要检查相关的 Maps JavaScript API 和 Places 服务配置。如果服务器直接调用 Places Web Service,则要检查该请求实际对应的 Places API。新旧 Places 服务可能在控制台中显示为不同的 API,不能只根据相近的名称判断。

3. 检查具体的配额指标

进入实际项目的 API 配额页面,筛选生产请求使用的 API,然后逐项查看:

  • Limit name
  • Effective limit
  • Current usage
  • 是否存在自定义 quota override
  • 是否有值为 1 的每日或速率限制
  • 是否同时存在按天、按分钟和按用户统计的指标

如果有效限制被设为 1,可以编辑或删除该自定义限制,让它恢复默认值,或者申请符合业务流量的额度。

修改配额后,配置可能需要一段时间才能在所有请求路径上生效。不要通过连续高频重试来验证修改结果。

4. 检查 API key 限制

API key 通常有两类限制:

  • Application restrictions:HTTP referrers、IP addresses、Android apps 或 iOS apps
  • API restrictions:允许该 key 调用哪些 API

浏览器端 key 需要确认生产域名已加入 HTTP referrer 允许列表,例如:

https://example.com/*
https://www.example.com/*

服务端 key 如果使用 IP 限制,应填写实际的对外出口 IP,而不是服务器内网地址。

还要确认 API restrictions 包含请求实际调用的 API。不要为了排查而长期保留 unrestricted key。可以短暂使用受控的测试凭据定位问题,确认原因后立即恢复最小权限限制。

5. 查看完整错误响应

Places Web Service 的 JSON 响应通常包含状态和附加错误信息。应记录经过脱敏的完整响应,不要只保留页面展示的通用提示:

{
  "status": "OVER_QUERY_LIMIT",
  "error_message": "You have exceeded your daily request quota for this API."
}

如果使用 Maps JavaScript API,也要查看浏览器控制台是否同时出现其他错误,例如 key 无效、API 未授权、来源域名不在允许范围内或 billing 配置异常。与通用提示同时出现的具体错误,通常更有助于定位问题。

6. 检查请求突增和重复调用

即使每日配额显示为 unlimited,短时间内的请求速率仍可能超限。可以重点检查:

  • 输入框是否在每次 keyup 时立即发起请求
  • 同一组件是否被重复初始化
  • 页面重渲染后是否重复绑定监听器
  • 前端重试是否没有退避机制
  • 机器人或爬虫是否触发了自动补全请求
  • 服务端是否反复请求同一个地点的详情

Places Autocomplete 应使用防抖,并在适用时复用 session token。下面的示例只演示如何避免每次按键都触发业务逻辑,具体调用方式应与当前使用的 Places API 版本一致:

function debounce(fn, delay) {
  let timer;

  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), delay);
  };
}

const handlePlaceInput = debounce((value) => {
  if (value.trim().length < 3) {
    return;
  }

  // 在这里发起 autocomplete 请求
}, 300);

document.querySelector("#address").addEventListener("input", (event) => {
  handlePlaceInput(event.target.value);
});

服务端遇到短周期限流时,可以对允许重试的请求使用指数退避,但不要对已经确定的每日配额或配置错误无限重试:

async function requestWithBackoff(request, maxAttempts = 4) {
  for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
    const response = await request();

    if (response.ok) {
      return response;
    }

    if (response.status !== 429 || attempt === maxAttempts - 1) {
      throw new Error(`Request failed with HTTP ${response.status}`);
    }

    const delay = Math.min(1000 * 2 ** attempt, 8000);
    await new Promise((resolve) => setTimeout(resolve, delay));
  }
}

部分 Places 接口会返回 HTTP 200,再通过 JSON 中的 status 表示请求失败,因此不能只检查 HTTP 状态码。

快速定位方法

可以创建一个临时且限制严格的测试 key,并确认它满足以下条件:

  • 位于已正确绑定 billing 的目标项目
  • 只允许调用所需 API
  • 仅允许生产域名或固定测试 IP
  • 没有值为 1 的自定义配额

如果同一请求换用新 key 后恢复,问题通常出在旧 key、旧项目或相关配额配置上。如果仍然失败,则需要继续检查 API 启用状态、请求方式、短周期配额和账号计费状态。

测试 key 只能用于定位问题。确认原因后应将其删除或轮换,不能把它当作长期绕过配额的方案。

仍无法恢复时

向 Google Maps Platform 支持提交问题时,应提供:

  • Cloud project ID
  • 受影响的 API 名称
  • 请求发生的准确时间和时区
  • 完整错误状态及脱敏后的 error_message
  • API key 的脱敏标识
  • 配额页面中有效限制为 1 的指标名称
  • billing 绑定状态和相关截图
  • 问题是否只发生在生产环境
  • 典型失败请求的脱敏示例

不要提交完整 API key、签名密钥或其他可复用凭据。

最后需要核对整条请求链路,确保生产请求使用的 key、key 所属项目、项目启用的 Places API,以及该项目绑定的 billing 和有效配额彼此一致。只看到其中某一项显示 unlimited,不能证明实际请求拥有无限额度。

备注:内容仅供参考。