Google Maps Platform 网络服务是一系列 HTTP 接口,可为您的地图应用提供地理数据。
本指南介绍了一些常见做法,这些做法有助于设置 Web 服务请求和处理服务响应。如需查看 Geolocation API 的完整文档,请参阅开发者指南。
什么是网络服务?
Google Maps Platform Web 服务是一个接口,用于从外部服务请求地图 API 数据,并在您的地图应用中使用这些数据。根据 Google Maps Platform 服务条款中的许可限制,这些服务应与地图结合使用。
Maps API Web 服务使用 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 服务器发出请求。这种循环行为可能会使客户端与 Google 之间的网络过载,从而给许多方带来问题。
更好的方法是在每次尝试之间增加延迟时间,然后重试。通常,每次尝试都会按乘数因子增加延迟时间,这种方法称为指数退避。
例如,假设某个应用希望向 Time Zone API 发出以下请求:
https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510×tamp=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 调用同步到分钟的开始时间(即使在不同设备之间也是如此),而不是在一段时间内均匀分布。如果应用设计不当,在每分钟开始时,流量会激增至正常水平的 60 倍。
相反,一种可能的好设计是将第二个闹钟设置为随机选择的时间。 当第二个闹钟触发时,应用会调用所需的任何 API 并存储结果。当应用想要在分钟开始时更新其显示时,它会使用之前存储的结果,而不是再次调用 API。通过这种方法,API 调用会随着时间的推移均匀分布。此外,在更新显示内容时,API 调用不会延迟渲染。
除了分钟开始时间之外,您还应注意不要将小时开始时间和每天午夜开始时间作为同步时间。
处理响应
此部分介绍如何以动态方式从 Web 服务响应中提取这些值。
Google Maps Web 服务提供的响应易于理解,但对用户来说并不友好。执行查询时,您可能希望提取一些特定值,而不是显示一组数据。通常,您需要解析来自 Web 服务的响应,并仅提取您感兴趣的值。
您使用的解析方案取决于您是否以 JSON 格式返回输出。JSON 响应已经采用 Javascript 对象的形式,因此可以在客户端上通过 Javascript 本身进行处理。