Accéder à App Engine avec l'API Remote

ID de la région

Le REGION_ID est un code abrégé que Google attribue en fonction de la région que vous sélectionnez lors de la création de votre application. Le code ne correspond pas à un pays ou une province, même si certains ID de région peuvent ressembler aux codes de pays et de province couramment utilisés. Pour les applications créées après février 2020, REGION_ID.r est inclus dans les URL App Engine. Pour les applications existantes créées avant cette date, l'ID de région est facultatif dans l'URL.

En savoir plus sur les ID de région

La bibliothèque de l'API Remote permet à tout client Python d'accéder aux services disponibles pour les applications App Engine.

Par exemple, si votre application App Engine utilise Datastore ou Google Cloud Storage, un client Python peut accéder à ces ressources de stockage à l'aide de l'API Remote.

L'API Remote vous permet d'accéder au datastore de votre application à partir d'une application s'exécutant sur votre ordinateur ou depuis l'interface système de l'API Remote interactive locale. Étant donné que l'API Remote interagit avec des services réels, des quotas et des ressources facturables sont utilisés.

Activer l'accès à l'API Remote dans votre application

Le moyen le plus simple d'activer l'API Remote pour votre application consiste à utiliser la directive builtins dans le fichier app.yaml de votre application, qui spécifie l'URL par défaut /_ah/remote_api/. Si vous souhaitez spécifier une autre URL, choisissez la directive url de ce même fichier.

builtin

La directive builtins du fichier app.yaml rend l'API Remote disponible à l'URL par défaut /_ah/remote_api :

runtime: python27
api_version: 1
threadsafe: true

builtins:
- remote_api: on

URL

L'utilisation de la directive url dans app.yaml vous permet de spécifier une autre URL à utiliser avec l'API Remote :

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

Veillez à déployer votre application sur App Engine après avoir effectué cette modification.

Utiliser l'interface système de l'API Remote

Le SDK App Engine pour Python comprend l'interface système de l'API Remote, qui permet d'appeler des commandes Python sur les services App Engine utilisés par votre application. Aucune autre forme d'authentification n'est nécessaire, car les identifiants que vous avez indiqués pour télécharger l'application sur App Engine sont automatiquement appliqués.

Pour démarrer l'interface système de l'API Remote, procédez comme suit :

  1. Appelez la commande suivante depuis une fenêtre de terminal sur votre ordinateur :

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

    Remplacez [SDK-INSTALL-DIRECTORY] par le chemin d'accès au SDK App Engine pour Python et [YOUR-PROJECT-ID] par votre ID de projet.

  2. Dans l'interface système interactive affichée, appelez les commandes Python que vous souhaitez exécuter. Par exemple, si votre application utilise Datastore, vous pouvez appeler la requête ndb suivante pour récupérer 10 enregistrements :

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

Utiliser l'API Remote dans un client local

Vous avez également la possibilité d'utiliser l'API Remote dans des applications locales pour accéder aux services utilisés par votre application s'exécutant dans App Engine.

Pour utiliser l'API Remote dans une application locale, procédez comme suit :

  1. Activez l'API Remote.

  2. Exportez la variable d'environnement PYTHONPATH de votre répertoire Python, par exemple :

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

    Remplacez ce chemin par les valeurs réelles de votre emplacement Python.

  3. Ajoutez l'emplacement du SDK App Engine pour Python à PYTHONPATH :

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

    Remplacez le chemin du SDK indiqué ci-dessus par votre chemin d'accès réel au SDK App Engine.

  4. Dans votre code client, importez dev_appserver et appelez dev_appserver.fix_sys_path() pour vous assurer que tous les modules du SDK App Engine sont correctement importés :

    try:
        import dev_appserver
        dev_appserver.fix_sys_path()
  5. Ajoutez le code remote_api_stub suivant à votre application, en veillant à lui transmettre votre numéro de projet dans votre code :

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

    Si vous n'utilisez pas l'URL par défaut /_ah/remote_api pour l'API Remote, vous devrez modifier le code ci-dessus pour refléter l'URL que vous utilisez. Pour accéder à la définition et à la documentation de remote_api_stub.ConfigureRemoteApiForOAuth, consultez le fichier SDK [SDK-INSTALL-DIRECTORY]/google/appengine/ext/remote_api/remote_api_stub.py.

  6. Ajoutez toutes les importations App Engine et le code Python nécessaires pour accéder aux services App Engine souhaités. L'exemple de code ci-dessous permet d'accéder au datastore du projet :

    
    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. Une fois votre application déployée dans App Engine, démarrez le client API Remote :

     python your-client.py YOUR-PROJECT-ID
    

    Remplacez your-client.py par votre module client et YOUR-PROJECT-ID par votre ID de projet. Cela suppose que votre client accepte l'ID de projet comme entrée de ligne de commande, comme indiqué dans l'exemple de code client.py.

Limitations et bonnes pratiques

Le module remote_api ne recule devant rien pour faire en sorte, dans la mesure du possible, de se comporter exactement comme le datastore App Engine natif. Dans certains cas, cela se fait aux dépens de l'efficacité de certaines opérations. Rappelez-vous donc des quelques points suivants lorsque vous utilisez le module remote_api :

Chaque requête du datastore implique un certain temps de transfert

Étant donné que vous accédez au datastore via HTTP, la surcharge et la latence sont plus élevés qu'avec un accès en local. Pour réduire le temps de réponse et diminuer la charge, essayez de limiter le nombre de transferts que vous effectuez en groupant par lot les requêtes de type GET et les requêtes de type PUT, et en récupérant des lots d'entités auprès des requêtes. Cette consigne est valable non seulement pour le module remote_api, mais aussi pour l'utilisation du datastore en général, car une opération par lot n'est considérée que comme une opération de datastore unique. Par exemple, au lieu de ceci :

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

vous pouvez faire cela :

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

Les deux exemples ont les mêmes effets, mais le dernier ne requiert que deux transferts au total, tandis que l'autre nécessite deux transferts pour chaque entité.

Les requêtes vers le module remote_api utilisent des quotas

Étant donné que le module remote_api exploite le protocole HTTP, chaque appel au datastore que vous effectuez entraîne une utilisation du quota pour les requêtes HTTP, les octets entrants et sortants, ainsi que du quota de datastore habituel. Gardez cela à l'esprit si vous utilisez remote_api pour effectuer des mises à jour groupées.

Les limites d'1 Mo des API s'appliquent

Comme pour une exécution native, la limite d'1 Mo sur les requêtes et réponses d'API est toujours valable. Si vos entités sont particulièrement importantes, il se peut que vous deviez limiter le nombre que vous récupérez ou le répartir dans le temps pour rester en deçà de cette limite. Malheureusement, cela est en contradiction avec la réduction des temps de transfert. Le mieux est d'utiliser des lots les plus grands possibles sans dépasser les limites de taille des requêtes ou des réponses. Pour la plupart des entités, cependant, il y a peu de risques que cela pose problème.

Éviter l'itération des requêtes

Un modèle courant avec accès au datastore est le suivant :

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

Lorsque vous effectuez cette opération, le SDK récupère les entités auprès du datastore par lots de 20, en renouvelant les lots après chaque utilisation. Étant donné que chaque lot doit être récupéré dans une requête distincte par remote_api, l'opération ne peut pas être efficace. À la place, remote_api exécute une requête entièrement nouvelle pour chaque lot, à l'aide de la fonctionnalité de décalage pour obtenir de meilleurs résultats.

Si vous connaissez le nombre d'entités qu'il vous faut, vous pouvez récupérer le tout dans une seule requête en demandant le nombre dont vous avez besoin :

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

Si vous ne savez pas de combien d'entités vous aurez besoin, vous pouvez utiliser les curseurs pour effectuer une itération efficace sur des ensembles de résultats volumineux. Cela vous permet également de contourner la limite de 1 000 entités, qui s'applique aux requêtes de datastore normales.

Les transactions sont moins efficaces

Pour la mise en œuvre de transactions via le module remote_api, ce dernier accumule des informations sur les entités récupérées dans la transaction, ainsi que les copies des entités qui ont été placées ou supprimées à l'intérieur de la transaction. Une fois que la transaction est validée, il envoie toutes ces informations au serveur App Engine, où il doit récupérer à nouveau toutes les entités qui ont été utilisées dans la transaction, vérifier qu'elles n'ont pas été modifiées, puis il doit appliquer et supprimer toutes les modifications effectuées par la transaction, et en effectuer un commit. En cas de conflit, le serveur effectue un rollback de la transaction et notifie le client, qui, à son tour, doit répéter tout le processus.

Cette approche fonctionne, et permet d'obtenir exactement les mêmes fonctionnalités que celles fournies par les transactions effectuées sur le datastore local, mais elle est inefficace. N'hésitez pas à utiliser des transactions lorsqu'elles sont nécessaires, mais en veillant à en limiter le nombre et la complexité afin de conserver une bonne efficacité.