Accesso ad App Engine con l'API Remote

ID regione

REGION_ID è un codice abbreviato assegnato da Google in base alla regione selezionata al momento della creazione dell'app. Il codice non corrispondono a un paese o a una provincia, anche se potrebbero essere visualizzati alcuni ID regione in modo simile ai codici paese e provincia di uso comune. Per le app create dopo il giorno Febbraio 2020, REGION_ID.r è incluso in URL di App Engine. Per le app esistenti create prima di questa data, l'ID regione è facoltativo nell'URL.

Scopri di più sugli ID regione.

La libreria API remota consente a qualsiasi client Python di accedere ai servizi disponibili le applicazioni App Engine.

Ad esempio, se la tua applicazione App Engine utilizza Datastore in Google Cloud Storage, un client Python può accedere alle risorse di archiviazione utilizzando l'API Remote.

Puoi utilizzare l'API Remote per accedere al datastore della tua applicazione da un'app in esecuzione sul tuo computer locale o da una shell dell'API remota locale interattiva. La L'API Remote interagisce con servizi reali, quindi questo accesso utilizza quota e delle risorse fatturabili.

Attivare l'accesso remoto all'API nell'app

Il modo più semplice per abilitare l'API Remote per la tua applicazione è utilizzare builtins nel file app.yaml della tua app, che specifica la URL predefinito /_ah/remote_api/. Tuttavia, puoi utilizzare l'url nello stesso file per specificare un altro URL.

integrato

L'istruzione builtins nel file app.yaml rende l'API Remote disponibile all'URL predefinito /_ah/remote_api:

runtime: python27
api_version: 1
threadsafe: true

builtins:
- remote_api: on

URL

Se utilizzi l'istruzione url in app.yaml puoi specificare un URL diverso per da utilizzare con l'API Remote:

- url: /some-URL/*
  script: google.appengine.ext.remote_api.handler.application

Assicurati di eseguire il deployment della tua applicazione in App Engine dopo aver eseguito questa modifica.

Utilizzo della shell dell'API Remote

L'SDK Python include una shell dell'API Remote, che consente di richiamare Python sui servizi App Engine utilizzati dalla tua applicazione. Non è necessario fornire qualsiasi autenticazione aggiuntiva, perché questa utilizza automaticamente lo stesso le credenziali utilizzate per caricare l'app in App Engine.

Per avviare la shell dell'API Remote:

  1. Richiama il seguente comando da una finestra del terminale sul computer locale:

    SDK-INSTALL-DIRECTORY/remote_api_shell.py -s YOUR-PROJECT-ID. REGION_ID.r.appspot.com

    Sostituisci [SDK-INSTALL-DIRECTORY] con il percorso dell'SDK di App Engine per Python e [YOUR-PROJECT-ID] con il tuo ID progetto.

  2. Nella shell interattiva visualizzata, richiama i comandi Python che vuoi eseguire. Ad esempio, se la tua applicazione utilizza Datastore, potresti richiama la seguente query ndb per recuperare 10 record:

     >>> from google.appengine.ext import ndb
     >>>
     >>> # Fetch 10 keys from the datastore
     >>> ndb.Query().fetch(10, keys_only=True)
    

Utilizzo dell'API Remote in un client locale

Per accedere ai servizi utilizzati, puoi anche utilizzare l'API Remote nelle applicazioni locali dall'app in esecuzione in App Engine.

Per utilizzare l'API Remote in un'applicazione locale:

  1. Abilita l'API remota.

  2. Esporta la variabile di ambiente PYTHONPATH per la tua directory Python, per esempio:

     export PYTHONPATH=/usr/somedir/v3/bin/python2.7
    

    Sostituisci questo percorso con i valori effettivi della tua posizione in Python.

  3. Aggiungi la posizione dell'SDK di App Engine per Python a PYTHONPATH:

     export GAE_SDK_ROOT="/usr/local/home/mydir/google_appengine"
     export PYTHONPATH=${GAE_SDK_ROOT}:${PYTHONPATH}
    

    Sostituisci il percorso SDK mostrato sopra con il percorso effettivo ad App Engine l'SDK.

  4. Nel codice cliente, importa dev_appserver e chiama dev_appserver.fix_sys_path() per garantire che tutti i moduli SDK di App Engine importa correttamente:

    try:
        import dev_appserver
        dev_appserver.fix_sys_path()
  5. Aggiungi il seguente codice remote_api_stub alla tua applicazione, assicurandoti di passa il tuo ID progetto nel codice:

    remote_api_stub.ConfigureRemoteApiForOAuth(
        '{}.appspot.com'.format(project_id),
        '/_ah/remote_api')

    Se non utilizzi l'URL predefinito /_ah/remote_api per l'API Remote, dovrai è necessario modificare il codice riportato sopra per riflettere l'URL che stai utilizzando. Per definizione e documentazione di remote_api_stub.ConfigureRemoteApiForOAuth, consulta il file dell'SDK [SDK-INSTALL-DIRECTORY]/google/appengine/ext/remote_api/remote_api_stub.py.

  6. Aggiungi le importazioni di App Engine e il codice Python necessari per accedere all'app desiderata Engine Services. Il codice campione seguente accede al datastore del progetto:

    
    import argparse
    
    try:
        import dev_appserver
        dev_appserver.fix_sys_path()
    except ImportError:
        print('Please make sure the App Engine SDK is in your PYTHONPATH.')
        raise
    
    from google.appengine.ext import ndb
    from google.appengine.ext.remote_api import remote_api_stub
    
    
    def main(project_id):
        remote_api_stub.ConfigureRemoteApiForOAuth(
            '{}.appspot.com'.format(project_id),
            '/_ah/remote_api')
    
        # List the first 10 keys in the datastore.
        keys = ndb.Query().fetch(10, keys_only=True)
    
        for key in keys:
            print(key)
    
    
    if __name__ == '__main__':
        parser = argparse.ArgumentParser(
            description=__doc__,
            formatter_class=argparse.RawDescriptionHelpFormatter)
        parser.add_argument('project_id', help='Your Project ID.')
    
        args = parser.parse_args()
    
        main(args.project_id)
  7. Dopo aver eseguito il deployment dell'applicazione in App Engine, avvia il client API Remote:

     python your-client.py YOUR-PROJECT-ID
    

    Sostituzione di your-client.py con il modulo client e YOUR-PROJECT-ID con il tuo ID progetto. Questo presuppone che il client accetti l'ID progetto come input della riga di comando, seguendo l'esempio di codice client.py.

Limitazioni e best practice

Il modulo remote_api fa di tutto per fare in modo che, per quanto possibile, si comporta esattamente come il datastore nativo di App Engine. 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 di 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. Va bene non solo per remote_api, ma anche per l'uso del datastore in generale, poiché un'operazione batch è considerata come un singolo datastore operativa. Ad esempio, invece di questo:

for key in keys:
  rec = key.get()
  rec.foo = bar
  rec.put()

puoi fare questo:

records = ndb.get_multi(keys)
for rec in records:
  rec.foo = bar
  ndb.put_multi(records)

Entrambi gli esempi hanno lo stesso effetto, ma il secondo richiede solo due di andata e ritorno in totale, mentre il primo richiede due andata e ritorno per dell'oggetto.

Richieste di quota di utilizzo 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 limiti 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, potresti dover limitare le numero che recuperi o assegni contemporaneamente per rimanere al di sotto di questo limite. Questo conflitto riducendo al minimo i viaggi di andata e ritorno, purtroppo il miglior consiglio è quello di utilizzare batch più grandi possibili senza superare le dimensioni della richiesta o della risposta limitazioni. Tuttavia, per la maggior parte delle entità, è improbabile che si tratti di un problema.

Evita di ripetere l'iterazione delle query

Un pattern comune con l'accesso al datastore è il seguente:

q = MyModel.query()
for entity in q:
  # Do something with entity

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

Se sai di quante entità hai bisogno, puoi eseguire l'intero recupero in una richiedi il numero che ti serve:

entities = MyModel.query().fetch(100)
for entity in entities:
  # Do something with entity

Se non sai quante entità vuoi, puoi utilizzare cursors per eseguire in modo efficiente l'iterazione su set di risultati di grandi dimensioni. Anche questo permette di evitare il limite di 1000 entità imposto al datastore normale query.

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 c'è un conflitto, il server esegue il rollback della transazione e invia una notifica lato client, che dovrà poi ripetere il processo da capo.

Questo approccio funziona e duplica esattamente la funzionalità fornita transazioni sul datastore locale, ma è piuttosto inefficiente. A tutti i costi utilizzano le transazioni dove necessario, ma cerca di limitare il numero e la complessità delle transazioni eseguite nell'interesse dell'efficienza.