Best practice per l'utilizzo dei servizi web dell'API Route Optimization

I servizi web di Google Maps Platform sono una raccolta di interfacce HTTP dei servizi Google che forniscono dati geografici per le applicazioni per le mappe.

Questa guida descrive alcune pratiche comuni utili per configurare le richieste di servizi web e elaborare le risposte dei servizi web. Consulta la guida per gli sviluppatori per la documentazione completa dell'API Route Optimization.

Che cos'è un servizio web?

I servizi web di Google Maps Platform sono un'interfaccia per richiedere i dati dell'API di Google Maps da servizi esterni e utilizzare i dati all'interno delle applicazioni Maps. Questi servizi sono progettati per essere utilizzati insieme a una mappa, come previsto dalle limitazioni di licenza nei Termini di servizio di Google Maps Platform.

I servizi web delle API di Google Maps utilizzano richieste HTTP(S) a URL specifici, trasmettendo parametri URL e/o dati POST in formato JSON come argomenti ai servizi. In genere, questi servizi restituiscono i dati nel corpo della risposta come JSON per l'analisi e/o l'elaborazione da parte della tua applicazione.

L'esempio seguente mostra l'URL di una richiesta POST REST per il metodo optimizeTours:

https://routeoptimization.googleapis.com/v1/projects/PROJECT_NUMBER:optimizeTours

Sostituisci PROJECT_NUMBER con il numero o l'ID del progetto Cloud in cui è abilitata l'API Route Optimization.

Includi il tuo messaggio OptimizeToursRequest come corpo della richiesta JSON.

Nota: tutte le applicazioni API Route Optimization richiedono l'autenticazione. Scopri di più sulle credenziali di autenticazione.

Accesso SSL/TLS

HTTPS è obbligatorio per tutte le richieste di Google Maps Platform che utilizzano chiavi API o contengono dati utente. Le richieste effettuate tramite HTTP che contengono dati sensibili potrebbero essere rifiutate.

Creazione di un URL valido in corso...

Potresti pensare che un URL "valido" sia evidente, ma non è esattamente così. Un URL inserito all'interno di una barra degli indirizzi di un browser, ad esempio, potrebbe contenere caratteri speciali (ad es. "上海+中國"); il browser deve tradurre internamente questi caratteri in una codifica diversa prima della trasmissione. Per lo stesso motivo, qualsiasi codice che genera o accetta input UTF-8 potrebbe considerare "validi" gli URL con caratteri UTF-8, ma dovrebbe anche tradurre questi caratteri prima di inviarli a un server web. Questo processo è chiamato codifica URL o codifica a percentuale.

Caratteri speciali

Dobbiamo tradurre i caratteri speciali perché tutti gli URL devono essere conformi alla sintassi specificata dalla specifica URI (Uniform Resource Identifier). Ciò significa che gli URL devono contenere solo un sottoinsieme speciale di caratteri ASCII: i simboli alfanumerici familiari e alcuni caratteri riservati da utilizzare come caratteri di controllo all'interno degli URL. Questa tabella riassume questi caratteri:

Riepilogo dei caratteri dell'URL validi
ConfigurapersonaggiUtilizzo degli URL
Alfanumerico a 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 O P Q R S T U V W X Y Z 0 1 2 3 4 8 9 6 7 Stringhe di testo, utilizzo dello schema (http), porta (8080) e così via.
Non prenotato - . ~ Stringhe di testo
Riservata ! * ' ( ) ; : @ & = + $ , / ? % # [ ] Caratteri di controllo e/o stringhe di testo

Quando crei un URL valido, devi assicurarti che contenga solo i caratteri mostrati nella tabella Riepilogo dei caratteri URL validi. La creazione di un URL per utilizzare questo set di caratteri in genere comporta due problemi, uno di omissione e uno di sostituzione:

  • I caratteri che vuoi gestire esistono al di fuori di questo set. Ad esempio, i caratteri in lingue straniere come 上海+中國 devono essere codificati utilizzando i caratteri precedenti. Secondo una convenzione comune, gli spazi (non consentiti all'interno degli URL) vengono spesso rappresentati utilizzando anche il carattere più '+'.
  • Questi caratteri esistono all'interno del set precedente come caratteri riservati, ma devono essere utilizzati letteralmente. Ad esempio, ? viene utilizzato negli URL per indicare l'inizio della stringa di query; se vuoi utilizzare la stringa "? e i Mysterions," devi codificare il carattere '?'.

Tutti i caratteri da codificare nell'URL sono codificati utilizzando un carattere '%' e un valore esadecimale a due caratteri corrispondente al relativo carattere UTF-8. Ad esempio, 上海+中國 in UTF-8 verrebbe codificato nell'URL come %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B. La stringa ? and the Mysterians verrebbe codificata nell'URL come %3F+and+the+Mysterians o %3F%20and%20the%20Mysterians.

Caratteri comuni che richiedono la codifica

Ecco alcuni caratteri comuni che devono essere codificati:

Carattere non sicuro Valore codificato
Spazio %20
" %22
< %3C
> %3E
# %23
% %25
| %7C

La conversione di un URL che ricevi dall'input utente a volte è complessa. Ad esempio, un utente può inserire come indirizzo "Via Verdi". In genere, dovresti creare l'URL a partire dalle sue parti, trattando gli input utente come caratteri letterali.

Inoltre, gli URL hanno un limite di 16.384 caratteri per tutti i servizi web e le API web statiche di Google Maps Platform. Per la maggior parte dei servizi, questo limite di caratteri verrà raramente raggiunto. Tuttavia, tieni presente che alcuni servizi hanno diversi parametri che possono generare URL lunghi.

Uso educato delle API di Google

I client API dal design inadeguato possono eseguire un carico maggiore del necessario sia su internet sia sui server di Google. Questa sezione contiene alcune best practice per i client delle API. Seguendo queste best practice puoi evitare che la tua applicazione venga bloccata per abusi involontari delle API.

Backoff esponenziale

In rari casi potrebbe verificarsi un problema nell'elaborazione della tua richiesta, potresti ricevere un codice di risposta HTTP 4XX o 5XX oppure la connessione TCP potrebbe semplicemente non riuscire da qualche parte tra il tuo client e il server di Google. Spesso vale la pena ritentare la richiesta poiché la richiesta di follow-up potrebbe avere esito positivo quando l'originale non è andato a buon fine. Tuttavia, è importante non limitarsi a eseguire ripetutamente il loop delle richieste ai server di Google. Questo comportamento di loop può sovraccaricare la rete tra il client e Google, causando problemi a molte parti.

Un approccio migliore consiste nel riprovare con un ritardo crescente tra un tentativo e l'altro. Di solito, il ritardo viene aumentato di un fattore moltiplicativo a ogni tentativo, un approccio noto come Backoff esponenziale.

Ad esempio, considera un'applicazione che desidera effettuare questa richiesta all'API Time Zone:

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

Il seguente esempio Python mostra come eseguire la richiesta con backoff esponenziale:

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

Devi inoltre assicurarti che non ci sia un nuovo tentativo di codice più in alto nella catena di chiamate delle applicazioni che porta a richieste ripetute in rapida successione.

Richieste sincronizzate

Un numero elevato di richieste sincronizzate alle API di Google possono sembrare un attacco Distributed DoS (DDoS) sull'infrastruttura di Google ed essere trattate di conseguenza. Per evitare che ciò accada, devi assicurarti che le richieste API non siano sincronizzate tra i client.

Ad esempio, prendiamo in considerazione un'applicazione che visualizza l'ora nel fuso orario corrente. Questa applicazione probabilmente imposterà una sveglia nel sistema operativo del client attivando la sveglia all'inizio del minuto, in modo che sia possibile aggiornare l'ora visualizzata. L'applicazione non deve effettuare chiamate API nell'ambito dell'elaborazione associata all'allarme.

Effettuare chiamate API in risposta a un allarme fisso non è corretto, perché comporta la sincronizzazione delle chiamate API all'inizio dell'istante, anche tra dispositivi diversi, anziché una distribuzione uniforme nel tempo. Un'applicazione progettata male in questo modo produrrà un picco di traffico a livelli sessanta volte normali all'inizio di ogni minuto.

Una soluzione alternativa potrebbe essere quella di impostare una seconda sveglia su un orario scelto in modo casuale. Quando si attiva questo secondo allarme, l'applicazione chiama le API di cui ha bisogno e archivia i risultati. Quando l'applicazione vuole aggiornare la visualizzazione all'inizio del minuto, utilizza i risultati archiviati in precedenza anziché chiamare di nuovo l'API. Con questo approccio, le chiamate API vengono distribuite uniformemente nel tempo. Inoltre, le chiamate API non ritardano il rendering quando il display viene aggiornato.

A parte l'inizio del minuto, altri orari di sincronizzazione comuni a cui devi fare attenzione non sono gli orari in cui impostare il target sono l'inizio di un'ora e l'inizio di ogni giorno a mezzanotte.

Elaborazione risposte in corso...

Questa sezione illustra come estrarre questi valori in modo dinamico dalle risposte del servizio web.

I servizi web di Google Maps forniscono risposte facili da capire, ma non esattamente facili da usare. Quando esegui una query, anziché visualizzare un insieme di dati, probabilmente vorrai estrarre alcuni valori specifici. In genere, vorrai analizzare le risposte del servizio web ed estrarre solo i valori che ti interessano.

Lo schema di analisi utilizzato dipende dalla restituzione dell'output in formato JSON. Le risposte JSON, che sono già sotto forma di oggetti JavaScript, possono essere elaborate all'interno del codice JavaScript stesso sul client.