Google Maps Platform 网络服务是一组 HTTP 接口,可用于访问 Google 服务,为您的地图应用提供地理数据。
本指南介绍了一些常见的实践,这些实践对于设置 Web 服务请求和处理服务响应非常有用。如需查看 Geolocation API 的完整文档,请参阅开发者指南。
什么是网络服务?
Google Maps Platform 网络服务是一种接口,用于从外部服务请求 Maps API 数据,并在 Google 地图应用中使用这些数据。根据 Google Maps Platform 服务条款中的许可限制,这些服务旨在与地图搭配使用。
Google 地图 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 地图 Web 服务提供的响应虽然易于理解,但并不完全符合用户需求。执行查询时,您可能希望提取一些特定值,而不是显示一组数据。通常,您需要解析来自网络服务的响应,并仅提取您感兴趣的值。
您使用的解析方案取决于您是否以 JSON 格式返回输出。JSON 响应已采用 JavaScript 对象的形式,因此可以在客户端的 JavaScript 本身中进行处理。