API remota per servizi in bundle legacy

L'SDK Java include una libreria chiamata API remota che ti consente di accedere in modo trasparente ai servizi App Engine da qualsiasi applicazione Java. Ad esempio, puoi utilizzare l'API Remote per accedere a un datastore di produzione da un'app in esecuzione sulla tua macchina locale. Puoi anche utilizzare l'API Remote per accedere al datastore di un'app App Engine da un'altra app App Engine.

Configurazione dell'API remota sul server

Il componente server dell'API Remote è un servlet Java che fa parte del runtime App Engine per Java. Questo servlet riceve le richieste dal client API remota, le invia al servizio di backend appropriato e poi restituisce il risultato della chiamata al servizio al client. Per installare il servlet dell'API remota, aggiungi quanto segue a web.xml:

<servlet>
  <display-name>Remote API Servlet</display-name>
  <servlet-name>RemoteApiServlet</servlet-name>
  <servlet-class>com.google.apphosting.utils.remoteapi.RemoteApiServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>RemoteApiServlet</servlet-name>
  <url-pattern>/remote_api</url-pattern>
</servlet-mapping>

Il servlet restituisce un errore se non è presente un utente autenticato o se l'utente autenticato non è un amministratore dell'applicazione, pertanto non è necessario configurare alcuna sicurezza aggiuntiva. Una volta dipiegato l'app con queste impostazioni, qualsiasi app con il client API remota installato può utilizzare i suoi servizi. Sono inclusi i client Python che utilizzano l'API Python Remote.

Configurazione dell'API Remote su un client autonomo

Per configurare il componente client dell'API Remote per l'utilizzo all'interno di un'applicazione Java, aggiungi ${SDK_ROOT}/lib/impl/appengine-api.jar e ${SDK_ROOT}/lib/appengine-remote-api.jar al classpath. Quindi, nel codice, configura e installa l'API Remote:

import com.google.appengine.tools.remoteapi.RemoteApiInstaller;
import com.google.appengine.tools.remoteapi.RemoteApiOptions;

// ...
RemoteApiOptions options = new RemoteApiOptions()
    .server("[APP_ID].[REGION_ID].r.appspot.com", 443)
    .useApplicationDefaultCredential();

RemoteApiInstaller installer = new RemoteApiInstaller();
installer.install(options);
// ... all API calls executed remotely
installer.uninstall();

Il client API remota si baserà sulle Credenziali predefinite dell'applicazione che utilizzano OAuth 2.0.

Per eseguire una corsa delle credenziali:

gcloud auth application-default login

Puoi connetterti con la stessa facilità a un'app App Engine in esecuzione localmente nel server di sviluppo:

RemoteApiOptions options = new RemoteApiOptions()
    .server("localhost", 8888) // server name must equal "localhost"
    .useDevelopmentServerCredential();

Ecco un'applicazione Java completa che, quando viene eseguita, inserisce un'entità nel datastore:

public class RemoteApiExample {

  public static void main(String[] args) throws IOException {
    String serverString = args[0];
    RemoteApiOptions options;
    if (serverString.equals("localhost")) {
      options = new RemoteApiOptions().server(serverString,
        8080).useDevelopmentServerCredential();
    } else {
      options = new RemoteApiOptions().server(serverString,
        443).useApplicationDefaultCredential();
    }
    RemoteApiInstaller installer = new RemoteApiInstaller();
    installer.install(options);
    try {
      DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
      System.out.println("Key of new entity is " + ds.put(new Entity("Hello Remote API!")));
    } finally {
      installer.uninstall();
    }
  }
}

Configurazione dell'API remota su un client App Engine

Puoi anche utilizzare l'API Remote per accedere ai servizi di un'applicazione App Engine da un'altra applicazione App Engine. Devi aggiungere ${SDK_ROOT}/lib/appengine-remote-api.jar alla tua directory WEB-INF/lib e poi, nell'app client App Engine, configurare e installare l'API Remote come hai fatto nel client Java autonomo.

Tieni presente che RemoteApiInstaller installa l'API Remote solo nel thread che esegue l'installazione, quindi fai attenzione a non condividere istanze di questa classe tra i thread.

Utilizzo dell'API remota con Maven

Per utilizzare la funzionalità dell'API remota nel tuo progetto Maven, aggiungi le seguenti dipendenze al file pom.xml del progetto:

<dependency>
  <groupId>com.google.appengine</groupId>
  <artifactId>appengine-remote-api</artifactId>
  <version>1.9.64</version>
</dependency>
<dependency>
  <groupId>com.google.appengine</groupId>
  <artifactId>appengine-api-1.0-sdk</artifactId>
  <version>1.9.64</version>
</dependency>

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 potrebbero essere. Quando utilizzi remote_api, tieni presente quanto segue:

Ogni richiesta di datastore richiede un round trip

Poiché accedi al datastore tramite HTTP, il sovraccarico e la latenza sono leggermente superiori rispetto all'accesso locale. Per velocizzare il processo e diminuire il carico, prova a limitare il numero di viaggi di andata e ritorno che effettui raggruppando get e put e recuperando 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.

Richieste alla quota di utilizzo di remote_api

Poiché remote_api opera tramite HTTP, ogni chiamata al datastore comporta un utilizzo della quota per le richieste HTTP, i byte in entrata e in uscita, nonché la consueta quota del datastore. Tieni presente questo aspetto se utilizzi remote_api per eseguire aggiornamenti collettivi.

Si applicano i limiti dell'API di 1 MB

Come per l'esecuzione nativa, si applica ancora il limite di 1 MB per le richieste e le risposte dell'API. Se le entità sono particolarmente grandi, potresti dover limitare il numero di elementi che recuperi o inserisci alla volta 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 persone non è 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 è possibile farlo in modo efficiente. Al contrario, remote_api esegue una query completamente nuova per ogni batch, utilizzando la funzionalità di offset per visualizzare altri 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, accumula informazioni sulle entità recuperate all'interno della transazione, insieme a copie delle entità inserite o eliminate all'interno della transazione. Quando la transazione viene eseguita, invia tutte queste informazioni al server App Engine, dove deve recuperare di nuovo tutte le entità utilizzate nella transazione, verificare che non siano state modificate, quindi inserire ed eliminare tutte le modifiche apportate dalla transazione ed eseguirne 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 dalle transazioni nel 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.