使用 Geolocation API 网络服务的最佳实践

Google Maps Platform 网络服务是一系列 HTTP 接口,供 Google 为您的地图应用提供地理数据的服务。

本指南介绍了一些在设置 Google Cloud 控制台时 Web 服务 请求和处理服务响应。请参阅开发者指南 获取 Geolocation API 的完整文档。

什么是网络服务?

Google Maps Platform 网络服务是一个用于从以下位置请求 Maps API 数据的接口: 外部服务和使用地图应用中的数据。这些服务 按照 许可限制

Maps API 网络服务使用对特定网址的 HTTP(S) 请求,传递网址参数和/或 JSON 格式的 POST 数据作为服务的参数。通常,这些服务会在 响应正文作为用于解析的 JSON 和/或处理

使用 POST 将地理位置请求发送到以下网址:

https://www.googleapis.com/geolocation/v1/geolocate?key=YOUR_API_KEY

注意:所有 Geolocation API 应用都需要进行身份验证。 详细了解身份验证凭据

SSL/TLS 访问

对于所有使用 API 密钥或包含用户信息的 Google Maps Platform 请求,都必须使用 HTTPS 数据。通过 HTTP 发出的包含敏感数据的请求可能会被拒绝。

合理使用 Google API

设计不合理的 API 客户端可能会给互联网和 Google 的服务器。本部分包含适用于 API 客户端的一些最佳做法。已关注 这些最佳做法可帮助您避免应用因无意间滥用 这些 API。

指数后退

在极少数情况下,处理您的请求时可能会出错;您可能会收到 4XX 或 5XX HTTP 否则 TCP 连接可能只是因为您的客户端与 Google 的 服务器。通常有必要重试请求 原始请求失败时,后续请求可能会成功。但重要的是 会反复向 Google 服务器发出请求。这种循环行为会导致 网络,给多方带来问题。

更好的方法是不断增加两次重试之间的延迟。通常, 每次尝试都以乘积因子增加延迟,这种方法称为 指数退避算法

例如,假设有一个应用程序希望向 Time Zone API:

https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510&timestamp=1331161200&key=YOUR_API_KEY

下面的 Python 示例显示了如何通过指数后退发起请求:

import json
import time
import urllib.error
import urllib.parse
import urllib.request

# The maps_key defined below isn't a valid Google Maps API key.
# You need to get your own API key.
# See https://developers.google.com/maps/documentation/timezone/get-api-key
API_KEY = "YOUR_KEY_HERE"
TIMEZONE_BASE_URL = "https://maps.googleapis.com/maps/api/timezone/json"


def timezone(lat, lng, timestamp):

    # Join the parts of the URL together into one string.
    params = urllib.parse.urlencode(
        {"location": f"{lat},{lng}", "timestamp": timestamp, "key": API_KEY,}
    )
    url = f"{TIMEZONE_BASE_URL}?{params}"

    current_delay = 0.1  # Set the initial retry delay to 100ms.
    max_delay = 5  # Set the maximum retry delay to 5 seconds.

    while True:
        try:
            # Get the API response.
            response = urllib.request.urlopen(url)
        except urllib.error.URLError:
            pass  # Fall through to the retry loop.
        else:
            # If we didn't get an IOError then parse the result.
            result = json.load(response)

            if result["status"] == "OK":
                return result["timeZoneId"]
            elif result["status"] != "UNKNOWN_ERROR":
                # Many API errors cannot be fixed by a retry, e.g. INVALID_REQUEST or
                # ZERO_RESULTS. There is no point retrying these requests.
                raise Exception(result["error_message"])

        if current_delay > max_delay:
            raise Exception("Too many retry attempts.")

        print("Waiting", current_delay, "seconds before retrying.")

        time.sleep(current_delay)
        current_delay *= 2  # Increase the delay each time we retry.


if __name__ == "__main__":
    tz = timezone(39.6034810, -119.6822510, 1331161200)
    print(f"Timezone: {tz}")

您还应该注意,应用调用中并没有更高的重试代码 快速连续地重复请求。

同步请求

大量向 Google API 同步的请求看起来就像是 Google 的基础架构受到拒绝服务攻击 (DDoS) 攻击,并受到相应处理。接收者 应确保 API 请求未同步 相互通信

例如,假设某个应用显示当前时区的时间。 此应用可能会在客户端操作系统中设置警报,在 分钟的开始时间,以便更新显示的时间。应用应 不会在与该警报关联的处理过程中进行任何 API 调用。

进行 API 调用来响应固定警报是很不好的,因为它会导致 API 调用 同步到分钟开始,即使在不同的设备之间,也不会 会随时间的推移而均匀分布。如果一个设计不合理的应用执行此操作,将会产生 在每分钟开始时将流量设置为正常水平的六十倍。

相反,一种可能的良好设计是将第二个警报设置为随机选择的时间。 当第二个闹铃触发时,应用会调用所需的任何 API 并存储 结果。当应用希望在分钟开始时更新其显示内容时,它会使用 而无需再次调用该 API。通过这种方法,API 调用 会随着时间均匀分布此外,当显示设备处于隐藏状态时,API 调用不会 正在更新。

除了从头到尾,其他常见的同步时间 定位到某个小时的开始和每天开始的午夜。

处理响应

此部分介绍如何以动态方式从 Web 服务响应中提取这些值。

Google 地图网络服务提供的响应易于 可以理解,但并不完全便于用户使用。执行查询时, 您可能需要提取一些特定的 值。通常,您需要从网络上解析 服务,并仅提取您感兴趣的值。

您使用的解析架构取决于您是否返回 以 JSON 格式输出。JSON 响应,格式已是 JavaScript 对象,可在 JavaScript 本身内处理 在客户端上运行