Como acessar o App Engine com a API Remote

ID da região

O REGION_ID é um código abreviado que o Google atribui com base na região que você selecionou ao criar o aplicativo. O código não corresponde a um país ou estado, ainda que alguns IDs de região sejam semelhantes aos códigos de país e estado geralmente usados. Para apps criados após fevereiro de 2020, o REGION_ID.r está incluído nos URLs do App Engine. Para apps existentes criados antes dessa data, o ID da região é opcional no URL.

Saiba mais sobre IDs de região.

A biblioteca da API Remote permite que qualquer cliente Python acesse serviços disponíveis para aplicativos do App Engine.

Por exemplo, caso seu aplicativo do App Engine use Datastore ou Google Cloud Storage, um cliente Python poderá acessar esses recursos de armazenamento usando a API Remote.

Use a API Remote para acessar o armazenamento de dados do aplicativo de um app em execução na máquina local ou de um shell da API Remote interativo local. A API Remote interage com serviços reais. Dessa maneira, esse acesso usa recursos de cota e faturáveis.

Como ativar o acesso à API Remote no app

A maneira mais fácil de ativar a API Remote para seu aplicativo é usar a diretiva builtins no arquivo app.yaml do aplicativo, que especifica o URL padrão /_ah/remote_api/. No entanto, é possível usar a diretiva url nesse mesmo arquivo para especificar outro URL.

builtin

A diretiva builtins no arquivo app.yaml torna a API Remote disponível no URL padrão /_ah/remote_api:

runtime: python27
api_version: 1
threadsafe: true

builtins:
- remote_api: on

URL

O uso da diretiva url em app.yaml permite especificar um URL diferente para uso com a API Remote:

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

Não se esqueça de implantar o aplicativo no App Engine depois de fazer essa alteração.

Como usar o shell da API Remote

O SDK do Python inclui um shell da API Remote, que permite invocar comandos do Python em serviços do App Engine usados pelo aplicativo. Você não precisa fornecer autenticação adicional, porque são usadas automaticamente as mesmas credenciais que você usou para fazer upload do app para o App Engine.

Para iniciar o shell da API Remote:

  1. Digite o seguinte comando em uma janela de terminal na máquina local:

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

    Substitua [SDK-INSTALL-DIRECTORY] pelo caminho para o SDK do App Engine no Python, e [YOUR-PROJECT-ID] pelo ID do projeto.

  2. No shell interativo exibido, invoque os comandos do Python que você quer executar. Por exemplo, se o aplicativo usar o Datastore, será possível invocar a seguinte consulta ndb para buscar 10 registros:

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

Como usar a API Remote em um cliente local

Você também pode usar a API Remote em aplicativos locais para acessar serviços usados pelo app em execução no App Engine.

Para usar a API Remote em um aplicativo local:

  1. Ative a API Remote.

  2. Exporte a variável de ambiente PYTHONPATH para o diretório do Python, por exemplo:

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

    Substitua esse caminho pelos valores reais do local do Python.

  3. Adicione em PYTHONPATH o local do SDK do App Engine para Python:

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

    Substitua o caminho do SDK mostrado acima pelo caminho real para o App Engine SDK.

  4. No código do cliente, importe dev_appserver e chame dev_appserver.fix_sys_path() para garantir que todos os módulos do SDK do App Engine sejam importados corretamente:

    try:
        import dev_appserver
        dev_appserver.fix_sys_path()
  5. Adicione o seguinte código remote_api_stub ao aplicativo, certificando-se de transmitir o ID do projeto no seu código:

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

    Se você não usar o URL padrão /_ah/remote_api para a API Remote, você terá que alterar o código acima para refletir o URL que estiver usando. Para a definição e documentação de remote_api_stub.ConfigureRemoteApiForOAuth, consulte o arquivo [SDK-INSTALL-DIRECTORY]/google/appengine/ext/remote_api/remote_api_stub.py do SDK.

  6. Adicione todas as importações do App Engine necessárias e o código do Python para acessar os serviços do App Engine desejados. O seguinte código de exemplo acessa o armazenamento de dados do projeto:

    
    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. Com o aplicativo implantado no App Engine, inicie o cliente da API Remote:

     python your-client.py YOUR-PROJECT-ID
    

    Substituir your-client.py pelo seu módulo de cliente, e YOUR-PROJECT-ID pelo ID do projeto. Isso pressupõe que o cliente aceita o ID do projeto como entrada de linha de comando, seguindo a amostra de código client.py.

Limitações e práticas recomendadas

O módulo remote_api empenha um grande esforço para garantir que, até onde for possível, ele se comporte exatamente como o armazenamento de dados nativo do App Engine. Em alguns casos, isso significa executar operações de forma menos eficiente, comparado a outra situação. Ao usar o remote_api, lembre-se:

Cada solicitação do armazenamento de dados requer um percurso completo

Como você está acessando o armazenamento de dados por HTTP, há um pouco mais de sobrecarga e latência do que quando você o acessa localmente. Para agilizar as operações e diminuir a carga, limite o número de percursos de ida e volta por meio de operações em lote de "gets" e "puts" e pela busca de lotes de entidades nas consultas. Esse é um bom conselho não apenas para o módulo remote_api, mas para usar o armazenamento de dados em geral, porque uma operação em lote é considerada apenas como uma única operação do Datastore. Por exemplo, em vez de:

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

faça:

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

Os dois exemplos têm o mesmo efeito, mas o último requer apenas dois percursos completos no total, enquanto o primeiro exige dois para cada entidade.

Solicitações para uso da cota do remote_api

Como o remote_api opera com HTTP, cada chamada de armazenamento de dados que você faz utiliza cotas para solicitações HTTP, bytes de entrada e saída, além da cota de armazenamento de dados comum esperada. Lembre-se disso se você estiver usando o remote_api para fazer atualizações em massa.

O limite de 1 MB da API se aplica

Assim como ocorre na execução nativa, o limite de 1 MB para solicitações e respostas da API ainda é aplicável. No caso de entidades grandes, é preciso limitar o número de buscas ou inserções por vez para permanecer abaixo desse limite. Infelizmente, isso causa um conflito com os percursos de ida e volta minimizadores. Por isso, a melhor dica é usar os maiores lotes possíveis sem passar pelas limitações de tamanho de solicitação ou resposta. No entanto, isso provavelmente não será problema para a maioria das entidades.

Evite a iteração de consultas

Veja a seguir um padrão comum no acesso do armazenamento de dados:

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

Ao fazer isso, o SDK busca entidades do armazenamento de dados em lotes de 20, buscando um lote novo após a utilização dos existentes. Como o remote_api deve buscar cada lote em uma solicitação separada, ele não consegue fazer isso com tanta eficácia. Em vez disso, o método remote_api executa uma consulta totalmente nova para cada lote, usando o recurso de deslocamento para se aprofundar ainda mais nos resultados.

Se você souber a quantidade de entidades que precisa, faça a busca inteira solicitando o número de entidades de que você precisa:

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

Se você não souber quantas entidades precisa, use cursores para iterar de forma eficiente em grandes conjuntos de resultados. Isso também evita o limite de 1.000 entidades imposto nas consultas normais ao armazenamento de dados:

As transações são menos eficientes

Para implementar as transações por meio do remote_api, as informações são acumuladas em entidades buscadas na transação, além de cópias das entidades que foram inseridas ou excluídas na transação. Quando executada, a transação envia todas essas informações para o servidor do App Engine, em que é necessário buscar novamente todas as entidades usadas na transação, verificar se não foram modificadas e, em seguida, inserir e excluir todas as alterações feitas pela transação e executá-la. Se houver um conflito, o servidor reverterá a transação e notificará o sistema do cliente, que deverá repetir o processo.

Essa abordagem funciona e duplica exatamente o recurso fornecido pelas transações no armazenamento de dados local, mas é ineficiente. Para não ter dúvidas, use as transações onde forem necessárias, mas tente limitar o número e a complexidade das que forem executadas visando a eficiência.