Geolocation API ウェブサービスを使用する際のベスト プラクティス

Google Maps Platform のウェブサービスは、Google サービスへの HTTP インターフェースを集めたもので、地図アプリケーションに地理データを提供します。

このガイドでは、ウェブサービス リクエストの設定やサービス レスポンスの処理に役立つ一般的なプラクティスについて説明します。Geolocation API の詳しいドキュメントについては、デベロッパー ガイドをご覧ください。

ウェブサービスとは

Google Maps Platform ウェブサービスは、外部サービスから Maps API データをリクエストし、マップ アプリケーション内でデータを使用するためのインターフェースです。これらのサービスは、Google Maps Platform 利用規約のライセンス制限に従い、地図と組み合わせて使うように設計されています。

Maps API のウェブサービスは、特定の URL に対して HTTP(S) リクエストを使用し、URL パラメータや JSON 形式の POST データを引数としてサービスに渡します。通常、これらのサービスは、アプリケーションで解析または処理できるように、レスポンス本文のデータを JSON として返します。

Geolocation リクエストは、次の URL に 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&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 リクエストがクライアント間で同期されないようにする必要があります。

たとえば、現在のタイムゾーンで時刻を表示するアプリについて考えてみましょう。このアプリケーションでは、時刻を更新できるように、クライアント オペレーティング システムが毎分 0 秒にアラームを起こすアラームを設定します。アプリは、このアラームに関連付けられた処理の一部として API を呼び出さないでください

固定アラームに応じて API 呼び出しを行うと、異なるデバイス間でも、API 呼び出しは時間の経過とともに均等に分散されず、毎分 0 分に同期されるため、適していません。このような設計の問題があるアプリケーションでは、毎分 00:00 に通常の 60 倍のレベルでトラフィックが急増します。

代わりに、ランダムに選択された時刻に 2 つ目のアラームを設定することが有効な設計の一つです。この 2 回目のアラームが発生すると、アプリは必要な API を呼び出して、結果を保存します。時刻の開始時に表示を更新する場合、API を再度呼び出すのではなく、以前に保存された結果を使用します。この方法では、API 呼び出しは時間の経過とともに均等に分散します。さらに、API 呼び出しによって、ディスプレイの更新時にレンダリングが遅延することはありません。

毎正時以外の一般的な同期時刻は、1 時間の開始時や、毎正時の深夜 0 時にターゲットにしないでください。

レスポンスの処理

このセクションでは、これらの値をウェブサービス レスポンスから動的に抽出する方法について説明します。

Google マップのウェブサービスが提供するレスポンスは理解しやすいものの、必ずしもユーザー フレンドリーなものではありません。クエリを実行するときに、データセットを表示するのではなく、特定の値を抽出したい場合があります。通常は、ウェブサービスからのレスポンスを解析し、必要な値のみを抽出します。

使用する解析スキームは、出力を JSON で返すかどうかによって異なります。すでに JavaScript オブジェクトの形式になっている JSON レスポンスは、クライアントの JavaScript 自体内で処理できます。