Best Practices für die Nutzung der Roads API-Webdienste

Die Google Maps Platform-Webdienste sind eine Sammlung von HTTP-Schnittstellen zu Google-Diensten, die geografische Daten für Ihre Kartenanwendungen bereitstellen.

In diesem Leitfaden werden einige allgemeine Vorgehensweisen beschrieben, die zum Einrichten Ihrer Webdienstanfragen und zur Verarbeitung von Dienstantworten hilfreich sind. Eine vollständige Dokumentation der Roads API finden Sie im Entwicklerhandbuch.

Was ist ein Webdienst?

Google Maps Platform-Webdienste sind eine Schnittstelle, über die Sie Maps API-Daten von externen Diensten anfordern und die Daten in Ihren Maps-Anwendungen verwenden können. Diese Dienste wurden für die Verwendung in Verbindung mit einer Karte entwickelt. Dabei gelten die Lizenzbeschränkungen in den Nutzungsbedingungen der Google Maps Platform.

Die Google Maps APIs-Webdienste verwenden HTTP(S)-Anfragen an bestimmte URLs und übergeben URL-Parameter und/oder POST-Daten im JSON-Format als Argumente an die Dienste. Im Allgemeinen geben diese Dienste Daten in der HTTP(S)-Anfrage als JSON zum Parsen und/oder Verarbeiten durch Ihre Anwendung zurück.

Eine typische Roads API-Webdienstanfrage hat in der Regel die folgende Form:

https://roads.googleapis.com/v1/snapToRoads?parameters&key=YOUR_API_KEY

Dabei gibt snapToRoads den angeforderten Dienst an. Weitere Straßendienste sind nearestRoads und speedLimits.

Hinweis: Alle Roads API-Anwendungen erfordern eine Authentifizierung. Weitere Informationen zu Anmeldedaten für die Authentifizierung

SSL-/TLS-Zugriff

HTTPS ist für alle Google Maps Platform-Anfragen erforderlich, die API-Schlüssel verwenden oder Nutzerdaten enthalten. Anfragen über HTTP, die sensible Daten enthalten, können abgelehnt werden.

Gültige URL erstellen

Es mag den Anschein haben, dass „gültige“ URLs eine Selbstverständlichkeit sind. Das ist jedoch nicht der Fall. So kann beispielsweise eine URL, die in die Adresszeile eines Browsers eingegeben wird, Sonderzeichen wie "上海+中國" enthalten; der Browser muss diese Zeichen vor der Übertragung intern in eine andere Codierung umwandeln. Ebenso ist es möglich, dass Code, der UTF-8-Eingaben erzeugt oder akzeptiert, URLs mit UTF-8-Zeichen als „gültig“ behandelt; diese Zeichen müssten jedoch vor dem Senden an einen Webbrowser ebenfalls umgewandelt werden. Dieser Vorgang wird als URL-Codierung oder Prozentcodierung bezeichnet.

Sonderzeichen

Sonderzeichen müssen umgewandelt werden, da alle URLs der Syntax entsprechen müssen, die in der Spezifikation Uniform Resource Identifier (URI) angegeben ist. Das bedeutet, dass URLs nur einen Teil der ASCII-Zeichen enthalten dürfen: die bekannten alphanumerischen Symbole und einige reservierte Zeichen, die in den URLs als Steuerzeichen dienen. Hier eine Übersicht:

Gültige URL-Zeichen
ZeichensatzcharactersVerwendung in der URL
Alphanumerisch b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N N P P R R S T U V W X Y Z 0 1 2 3 4 5 5 9 Textstrings, Schemas (http), Portangaben (8080) usw.
Nicht reserviert - _ . ~ Text
Reserviert ! * ' ( ) ; : @ & = + $ , / ? % # [ ] Steuerzeichen und/oder Text

Beachte bei der Generierung einer URL, dass sie nur die in der Tabelle aufgeführten Zeichen enthalten darf. Die Anpassung der URL an diesen Zeichensatz führt in der Regel zu zwei Problemen, nämlich dass Zeichen weggelassen oder ersetzt werden müssen:

  • Die Zeichen, die du verarbeiten möchtest, sind nicht im obigen Zeichensatz enthalten. So müssen beispielsweise Zeichen ausländischer Sprachen, wie 上海+中國, mithilfe der oben angegebenen Zeichen codiert werden. Auch werden Leerzeichen, die innerhalb von URLs nicht zulässig sind, entsprechend den geltenden Konventionen oftmals durch das Zeichen '+' dargestellt.
  • Die Zeichen sind im obigen Zeichensatz als reservierte Zeichen enthalten, müssen aber im ursprünglichen Sinn des Zeichens verwendet werden. So wird beispielsweise ? in URLs für den Beginn eines Abfragestrings verwendet. Möchtest du es stattdessen für den Text „? and the Mysterions“ verwenden, musst du das Zeichen '?' codieren.

Alle Zeichen, die als URL codiert werden sollen, werden mithilfe des Zeichens '%' und eines Hexadezimalwerts aus zwei Zeichen codiert, der ihrem UTF-8-Zeichen entspricht. So würde zum Beispiel der UTF-8-String 上海+中國 durch die URL-Codierung in %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B umgewandelt. Und aus ? and the Mysterians würde %3F+and+the+Mysterians oder %3F%20and%20the%20Mysterians werden.

Allgemeine Zeichen, die codiert werden müssen

Folgende häufig vorkommende Zeichen müssen codiert werden:

Unsicheres Zeichen Codierter Wert
Leertaste %20
" %22
< %3C
> %3E
# %23
% %25
| %7C

Die Konvertierung von URLs, die aus Nutzereingaben empfangen werden, kann manchmal Probleme mit sich bringen. Beispielsweise kann ein Nutzer eine Adresse als „5th&Main St.“ eingeben. Im Allgemeinen solltest du die URL aus ihren Teilen erstellen und jede Nutzereingabe wortwörtlich betrachten.

Außerdem sind URLs für alle Google Maps Platform-Webdienste und statischen Web APIs auf 8.192 Zeichen beschränkt. Bei den meisten Diensten wird diese Begrenzung selten erreicht. Beachte jedoch, dass bestimmte Dienste einige Parameter haben, die zu langen URLs führen können.

Respektvolle Nutzung der Google APIs

Schlecht konzipierte API-Clients können sowohl auf dem Internet als auch auf Google-Servern mehr als nötig belasten. Dieser Abschnitt enthält einige bewährte Methoden für Kunden der APIs. Mit den folgenden Best Practices können Sie verhindern, dass Ihre Anwendung aufgrund von unbeabsichtigtem Missbrauch der APIs blockiert wird.

Exponentieller Backoff

In seltenen Fällen kann bei der Verarbeitung Ihrer Anfrage ein Fehler auftreten. Sie erhalten möglicherweise einen 4XX- oder 5XX-HTTP-Antwortcode oder die TCP-Verbindung zwischen Ihrem Client und dem Google-Server schlägt fehl. Häufig lohnt es sich, die Anfrage noch einmal zu senden, da die Folgeanfrage erfolgreich sein kann, wenn das Original fehlgeschlagen ist. Allerdings sollten Sie nicht einfach wiederholt Anfragen an die Google-Server senden. Durch diese Schleife kann das Netzwerk zwischen Ihrem Client und Google überlastet werden, was bei vielen Parteien zu Problemen führt.

Ein besserer Ansatz ist es, wiederholte Versuche in immer größeren Abständen durchzuführen. In der Regel erhöht sich die Verzögerung bei jedem Versuch um einen multiplikativen Faktor. Dieser Ansatz wird als exponentieller Backoff bezeichnet.

Angenommen, eine Anwendung möchte diese Anfrage an die Time Zone API senden:

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

Im folgenden Beispiel mit Python wird gezeigt, wie die Anforderung mit exponentiellem Backoff durchgeführt wird:

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}")

Achten Sie außerdem darauf, dass der Code in der Anwendungsaufrufkette nicht wiederholt wird, was schnell hintereinander zu wiederholten Anfragen führt.

Synchronisierte Anforderungen

Eine große Anzahl synchronisierter Anfragen an die APIs von Google kann wie ein DDoS-Angriff (Distributed Denial of Service) auf die Infrastruktur von Google aussehen und entsprechend behandelt werden. Um dies zu vermeiden, solltest du darauf achten, dass API-Anfragen nicht zwischen Clients synchronisiert werden.

Angenommen, eine Anwendung zeigt die Zeit in der aktuellen Zeitzone an. Diese Anwendung wird wahrscheinlich einen Wecker im Betriebssystem des Clients stellen, der zu Beginn der Minute aufwacht, damit die angezeigte Zeit aktualisiert werden kann. Die Anwendung sollte im Rahmen der Verarbeitung dieses Alarms keine API-Aufrufe ausführen.

API-Aufrufe als Reaktion auf einen festen Alarm sind schlecht, da dies dazu führt, dass die API-Aufrufe bis zum Beginn der Minute synchronisiert werden, auch zwischen verschiedenen Geräten, anstatt dass sie gleichmäßig verteilt werden. Eine schlecht konzipierte Anwendung, die dies tut, erzeugt zu Beginn jeder Minute ein 60-mal höheres Zugriffsaufkommen.

Stattdessen wird bei einer guten Lösung ein zweiter Alarm für eine zufällig gewählte Zeit festgelegt. Wenn dieser zweite Wecker die Anwendung auslöst, ruft sie alle erforderlichen APIs auf und speichert die Ergebnisse. Wenn die Anzeige zu Beginn der Minute aktualisiert werden soll, verwendet die App zuvor gespeicherte Ergebnisse, anstatt die API noch einmal aufzurufen. Bei diesem Ansatz werden API-Aufrufe gleichmäßig über die Zeit verteilt. Außerdem wird das Rendering durch die API-Aufrufe nicht verzögert, wenn die Anzeige aktualisiert wird.

Abgesehen vom Beginn der Minute sollten Sie auch andere gängige Synchronisierungszeiten, die Sie nicht festlegen sollten, zu Beginn einer Stunde und zu Beginn jedes Tages um Mitternacht festlegen.

Antworten verarbeiten

In diesem Abschnitt wird gezeigt, wie diese Werte dynamisch aus Webdienstanforderungen extrahiert werden können.

Die Google Maps-Webdienste bieten Antworten, die leicht verständlich, aber nicht gerade benutzerfreundlich sind. Wenn Sie eine Abfrage ausführen, möchten Sie wahrscheinlich einige bestimmte Werte extrahieren, anstatt einen Datensatz anzuzeigen. Generell sollten Sie Antworten vom Webdienst parsen und nur die für Sie interessanten Werte extrahieren.

Welches Parsingschema Sie verwenden, hängt davon ab, ob Sie eine Ausgabe im JSON-Format zurückgeben. JSON-Antworten, die bereits in Form von JavaScript-Objekten vorliegen, können in JavaScript selbst auf dem Client verarbeitet werden.