Accesso ad App Engine con l'API Remote

Google Cloud CLI include un pacchetto remote_api che ti consente di utilizzare in modo trasparente ai servizi App Engine da qualsiasi applicazione Go. Ad esempio, puoi utilizzare l'API Remote per accedere a Datastore da un'app in esecuzione sulla tua macchina locale o da un'altra delle tue app App Engine.

Per visualizzare i contenuti del pacchetto remote_api, consulta la documentazione di riferimento del pacchetto remote_api.

Abilitazione dell'API Remote

Innanzitutto, aggiungi l'handler remote_api url al app.yaml. Ad esempio:

- url: /_ah/remote_api
  script: _go_app

L'URL /_ah/remote_api viene mappato alla tua app Go. L'accesso a questo URL è limitato agli amministratori dell'applicazione dall'handler dell'API remota.

Quindi importerai il pacchetto remote_api in uno dei file pacchetti aggiungendo la seguente riga a uno qualsiasi dei tuoi file sorgente .go:

import _ "google.golang.org/appengine/remote_api"

Durante l'inizializzazione del programma, il pacchetto remote_api registra un gestore per il percorso /_ah/remote_api. L'underscore nella dichiarazione di importazione significa "importa questo pacchetto, ma non lo utilizzeremo direttamente". Senza il carattere underscore, durante la compilazione viene visualizzato il messaggio di errore "Importato, ma non utilizzato".

Infine, esegui il deployment dell'aggiornamento in App Engine. Ad esempio:

gcloud app deploy app.yaml

Utilizzo dell'API Remote in un client locale

L'API Remote può essere utilizzata per scrivere applicazioni locali che utilizzano i servizi App Engine e accedono al datastore. È importante notare che l'uso del telecomando L'API comporterà l'utilizzo della quota nell'applicazione a cui stai accedendo.

Prima di iniziare, assicurati che l'API Remote sia abilitata in App Engine un'applicazione. L'applicazione locale può utilizzare l'API Remote creando un contesto con remote_api.NewRemoteContext, che utilizza al posto dell'app standard Contesto del motore in tutte le chiamate API.

// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

package main

import (
	"log"
	"time"

	"golang.org/x/net/context"
	"golang.org/x/oauth2/google"

	"google.golang.org/appengine/datastore"
	"google.golang.org/appengine/remote_api"
)

func main() {
	const host = "<your-app-id>.appspot.com"

	ctx := context.Background()

	hc, err := google.DefaultClient(ctx,
		"https://www.googleapis.com/auth/appengine.apis",
		"https://www.googleapis.com/auth/userinfo.email",
		"https://www.googleapis.com/auth/cloud-platform",
	)
	if err != nil {
		log.Fatal(err)
	}

	remoteCtx, err := remote_api.NewRemoteContext(host, hc)
	if err != nil {
		log.Fatal(err)
	}

	q := datastore.NewQuery("Greeting").
		Filter("Date >=", time.Now().AddDate(0, 0, -7))

	log.Println(q.Count(remoteCtx))
}

Per eseguire questo codice, devi recuperare questi pacchetti:

$ go get google.golang.org/appengine/...
$ go get golang.org/x/oauth2/...

Devi fornire il nome host del tuo server e un http.Client nella chiamata a NewRemoteContext. Il http.Client fornito è responsabile del superamento le informazioni di autenticazione richieste in ogni richiesta.

Nell'esempio precedente, il valore DefaultClient di golang.org/x/oauth2/google fornisce le credenziali OAuth 2 tramite Credenziali predefinite dell'applicazione.

Limitazioni e best practice

Il modulo remote_api fa di tutto per assicurarsi che, per quanto possibile, si comporti esattamente come il datastore App Engine nativo. In alcuni casi, ciò significa fare cose meno efficienti di quanto non in caso contrario. Quando utilizzi remote_api, tieni presente quanto segue:

Ogni richiesta al datastore richiede un round trip

Poiché si accede al datastore tramite HTTP, l'overhead è leggermente superiore anziché in locale. Per velocizzare le cose riduci il carico, prova a limitare il numero di viaggi di andata e ritorno raggruppando e il recupero di batch di entità dalle query. Questo è un buon consiglio non solo per remote_api, ma anche per l'utilizzo del datastore in generale, perché un'operazione batch è considerata solo una singola operazione di Datastore.

Quota di utilizzo delle richieste a remote_api

Poiché remote_api opera su HTTP, ogni chiamata al datastore che effettui viene applicata per le richieste HTTP, byte in entrata e in uscita, nonché la quota di datastore che ti aspetti. Tieni presente questo aspetto se utilizzi remote_api per eseguire aggiornamenti collettivi.

Si applicano i limiti dell'API di 1 MB

Come quando viene eseguita in modo nativo, il limite di 1 MB per le richieste e le risposte API rimane . Se le entità sono particolarmente grandi, potrebbe essere necessario limitare il numero di elementi recuperati o inseriti contemporaneamente per rimanere al di sotto di questo limite. Purtroppo, questo è in conflitto con la minimizzazione dei round trip, quindi il consiglio migliore è utilizzare i batch più grandi possibili senza superare i limiti di dimensione della richiesta o della risposta. Tuttavia, per la maggior parte delle entità, è improbabile che si tratti di un problema.

Evita di eseguire l'iterazione sulle query

Quando esegui l'iterazione sulle query, l'SDK recupera le entità dal datastore in batch di 20, recuperando un nuovo batch ogni volta che esaurisce quelli esistenti. Poiché ogni batch deve essere recuperato in una richiesta separata da remote_api, non sono in grado di farlo in modo efficiente. Al contrario, remote_api esegue per ogni batch, utilizzando la funzionalità di offset per approfondire che consentono di analizzare i dati e visualizzare i risultati.

Se sai quante entità ti servono, puoi eseguire l'intero recupero in un'unica richiesta chiedendo il numero necessario.

Se non sai quante entità ti serviranno, puoi utilizzare i cursori per eseguire in modo efficiente l'iterazione su insiemi di risultati di grandi dimensioni. In questo modo, puoi anche evitare il limite di 1000 entità imposto alle normali query del datastore.

Le transazioni sono meno efficienti

Per implementare le transazioni tramite remote_api, informazioni sulle entità recuperate all'interno della transazione, insieme alle copie inserite o eliminate all'interno della transazione. Quando il commit della transazione, invia tutte queste informazioni all'App motore di ricerca, dove deve recuperare tutte le entità che sono state utilizzate nel transazione, verifica che non siano state modificate, quindi inserisci elimina tutte le modifiche apportate dalla transazione ed esegui il commit. Se si verifica un conflitto, il server esegue il rollback della transazione e invia una notifica al client, che deve ripetere la procedura da capo.

Questo approccio funziona e duplica esattamente la funzionalità fornita transazioni sul datastore locale, ma è piuttosto inefficiente. Utilizza le transazioni se necessarie, ma cerca di limitare il numero e la complessità di quelle che esegui per motivi di efficienza.