O Python 2 não é mais compatível com a comunidade. Recomendamos que você migre aplicativos do Python 2 para o Python 3.

Como as solicitações são tratadas

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, embora alguns IDs de região sejam semelhantes aos códigos de país e estado mais usados. A inclusão de REGION_ID.r em URLs do App Engine é opcional para aplicativos que já existem e, em breve, será obrigatória para todos os aplicativos novos.

Para garantir uma transição tranquila, estamos atualizando gradativamente o App Engine para usar IDs de região. Se ainda não tivermos atualizado seu projeto do Google Cloud, você não verá um ID da região para o aplicativo. Como o ID é opcional para os aplicativos que já existem, não será necessário atualizar os URLs nem fazer outras alterações quando o ID da região estiver disponível para os aplicativos já existentes.

Saiba mais sobre IDs de região.

Este documento descreve como um aplicativo do App Engine recebe solicitações e envia respostas. Para mais detalhes, consulte a referência sobre respostas e cabeçalhos de solicitação.

Se o aplicativo usa serviços, é possível endereçar solicitações para um serviço específico ou uma versão determinada desse serviço. Para mais informações sobre a capacidade de endereçamento do serviço, consulte Como as solicitações são encaminhadas.

Como processar solicitações

O aplicativo é responsável por iniciar um servidor da Web e processar as solicitações. É possível usar qualquer framework da Web disponível na linguagem de programação adotada.

Várias instâncias do aplicativo são executadas no App Engine e cada uma tem um servidor da Web próprio para processar as solicitações. Como cada solicitação pode ser encaminhada para qualquer instância, solicitações consecutivas do mesmo usuário não são necessariamente enviadas para a mesma instância. Uma instância pode processar várias solicitações simultaneamente. O número de instâncias pode ser ajustado automaticamente à medida que o tráfego muda. Também é possível alterar o número de solicitações simultâneas que uma instância pode processar. Basta configurar o elemento max_concurrent_requests no arquivo app.yaml.

Quando o App Engine recebe uma solicitação da Web para seu aplicativo, ele chama o script do gerenciador que corresponde ao URL, conforme descrito no arquivo de configuração app.yaml do aplicativo. O ambiente de execução do Python 2.7 aceita o padrão WSGI e o padrão CGI (links em inglês) para compatibilidade com versões anteriores. O WSGI é o preferido, e alguns recursos do Python 2.7 não funcionam sem ele. A configuração dos gerenciadores de script do seu aplicativo determina se uma solicitação é processada com WSGI ou CGI.

O script Python a seguir responde a uma solicitação com um cabeçalho HTTP e a mensagem Hello, World!.

import webapp2

class MainPage(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.write('Hello, World!')

app = webapp2.WSGIApplication([
    ('/', MainPage),
], debug=True)

Para expedir várias solicitações para cada servidor da Web paralelamente, marque seu aplicativo como threadsafe adicionando um threadsafe: true ao arquivo app.yaml. As solicitações simultâneas não estarão disponíveis se algum gerenciador de script usar CGI.

Cotas e limites

No App Engine, os recursos são alocados automaticamente para o aplicativo à medida que o tráfego aumenta. No entanto, há as seguintes restrições:

  • O App Engine reserva a capacidade de escalonamento automático para aplicativos com baixa latência, em que a resposta a uma solicitação ocorre em menos de um segundo. Aplicativos com latência muito alta exigem suporte Silver, Gold ou Platinum. Por exemplo, latência de mais de um segundo por solicitação no caso de muitas solicitações. Os clientes com esses níveis de suporte podem entrar em contato com nossos representantes para solicitar limites de capacidade mais altos.

  • Aplicativos que fazem muito uso da CPU podem gerar mais latência, a fim de compartilhar recursos de maneira eficiente com outros aplicativos nos mesmos servidores. Solicitações de arquivos estáticos estão isentas dos limites de latência.

Cada solicitação recebida para o aplicativo é contabilizada no limite de Solicitações. Os dados enviados em resposta a uma solicitação são contabilizados no limite de Largura de banda de saída (faturável).

Tanto as solicitações em HTTP quanto em HTTPS (seguro) contabilizam nos limites de Solicitações, Largura de banda de entrada (faturável) e Largura de banda de saída (faturável). A página "Detalhes da cota" do Console do Cloud também informa Solicitações seguras, Largura de banda de entrada segura e Largura de banda de saída segura como valores separados para fins informativos. Apenas solicitações HTTPS são contabilizadas nesses valores. Para mais informações, consulte a página Cotas.

Os limites a seguir se aplicam especificamente ao uso de gerenciadores de solicitações:

Limite Valor
tamanho da solicitação 32 megabytes
tamanho da resposta 32 megabytes
tempo limite da solicitação depende do tipo de escalonamento usado pelo aplicativo
número máximo total de arquivos (arquivos de aplicativos e arquivos estáticos) 10.000 no total
1.000 por diretório
tamanho máximo de um arquivo de aplicativo 32 megabytes
tamanho máximo de um arquivo estático 32 megabytes
tamanho máximo total de todos os arquivos de aplicativo e arquivos estáticos o primeiro 1 gigabyte é gratuito
US$ 0,026 por gigabyte por mês após o primeiro 1 gigabyte

Limites de respostas

As respostas dinâmicas são limitadas a 32 MB. Se um gerenciador de script gerar uma resposta maior do que esse limite, o servidor devolverá uma resposta vazia com um código de status 500 Erro interno do servidor. Essa limitação não se aplica a respostas que disponibilizam dados do Blobstore ou do Cloud Storage.

Cabeçalhos de solicitação

Uma solicitação HTTP recebida inclui os cabeçalhos HTTP enviados pelo cliente. Para fins de segurança, alguns cabeçalhos são limpos ou alterados por proxies intermediários antes de chegar ao aplicativo.

For saber more, consulte a referência sobre Cabeçalhos de solicitação.

Respostas a solicitações

O App Engine chama o script do gerenciador com um Request e espera o retorno do script. Todos os dados gravados no fluxo de saída padrão são enviados como a resposta HTTP.

Existem limites que se aplicam à resposta gerada e a resposta pode ser modificada antes de ser retornada ao cliente.

Para mais informações, consulte a referência sobre respostas a solicitações.

Respostas de streaming

O App Engine não é compatível com respostas de streaming em que os dados são enviados em blocos incrementais para o cliente enquanto uma solicitação está sendo processada. Todos os dados do seu código são coletados conforme descrito acima e enviados como uma única resposta HTTP.

Compactação de resposta

Se o cliente enviar cabeçalhos HTTP com a solicitação original indicando que ele pode aceitar conteúdo compactado (gzip), o App Engine compactará automaticamente os dados de resposta do gerenciador e anexará os cabeçalhos de resposta apropriados. Ele usará os cabeçalhos de solicitação Accept-Encoding e User-Agent para determinar se o cliente pode receber respostas compactadas de maneira confiável.

É possível que clientes personalizados indiquem que são capazes de receber respostas compactadas especificando os cabeçalhos Accept-Encoding e User-Agent com um valor de gzip. O Content-Type da resposta também é usado para determinar se a compactação é apropriada. Em geral, os tipos de conteúdo baseados em texto são compactados, enquanto os tipos de conteúdo binário não são.

Quando as respostas forem compactadas automaticamente pelo App Engine, o cabeçalho Content-Encoding será adicionado à resposta.

Como especificar um prazo para solicitação

O App Engine é otimizado para aplicativos com solicitações de curta duração, normalmente aquelas que levam poucas centenas de milissegundos. Aplicativos eficientes respondem com rapidez à maioria das solicitações. Caso contrário, o aplicativo não escalonará bem com a infraestrutura do App Engine.

Todas as solicitações para seu aplicativo precisam retornar uma resposta dentro do tempo limite máximo da solicitação. Se o aplicativo não responder até o tempo limite, o App Engine interromperá o gerenciador de solicitações. O ambiente de execução do Python interrompe o gerenciador de solicitações gerando um DeadlineExceededError do pacote google.appengine.runtime. Se o gerenciador de solicitação não capturar essa exceção, assim como acontece com todas as exceções não capturadas, o ambiente de execução retornará um erro de servidor HTTP 500 para o cliente.

O gerenciador de solicitação pode capturar esse erro para personalizar a resposta. O ambiente de execução dará ao gerenciador de solicitação um pouco mais de tempo (menos de um segundo) depois de gerar a exceção para preparar uma resposta personalizada.

class TimerHandler(webapp2.RequestHandler):
    def get(self):
        from google.appengine.runtime import DeadlineExceededError

        try:
            time.sleep(70)
            self.response.write('Completed.')
        except DeadlineExceededError:
            self.response.clear()
            self.response.set_status(500)
            self.response.out.write(
                'The request did not complete in time.')

Se não tiver retornado uma resposta ou gerado uma exceção até o segundo prazo, o gerenciador será encerrado e a resposta de erro padrão será retornada.

Logging

O servidor da web do App Engine captura tudo que o script de gerenciador grava no fluxo de saída padrão para a resposta à solicitação da Web. Ele também captura tudo que o script de gerenciador grava no fluxo de erros padrão e armazena isso como dados de registro. Cada solicitação recebe um request_id, um identificador exclusivo global com base no horário de início da solicitação. Os dados de registro do aplicativo podem ser visualizados no Console do Cloud usando o Cloud Logging.

O ambiente de execução Python do App Engine inclui suporte especial para o módulo de geração de registros da biblioteca padrão do Python para entender conceitos de geração de registros como níveis de registro ("debug", "info", "warning", "error", "critical").

import logging

import webapp2

class MainPage(webapp2.RequestHandler):
    def get(self):
        logging.debug('This is a debug message')
        logging.info('This is an info message')
        logging.warning('This is a warning message')
        logging.error('This is an error message')
        logging.critical('This is a critical message')

        try:
            raise ValueError('This is a sample value error.')
        except ValueError:
            logging.exception('A example exception log.')

        self.response.out.write('Logging example.')

app = webapp2.WSGIApplication([
    ('/', MainPage)
], debug=True)

Ambiente

O ambiente de execução define automaticamente muitas variáveis de ambiente. É possível definir mais em app.yaml. Das variáveis definidas automaticamente, algumas são especiais para o App Engine e outras fazem parte dos padrões WSGI ou CGI. O código Python pode acessar essas variáveis usando o dicionário os.environ.

As seguintes variáveis de ambiente são específicas do App Engine:

  • CURRENT_VERSION_ID: a versão principal e a versão secundária do aplicativo em execução no momento, como "X.Y". O número da versão principal ("X") é especificado no arquivo app.yaml do aplicativo. O número da versão secundária ("Y") é definido automaticamente quando cada versão do app é enviada para o App Engine. No servidor da Web de desenvolvimento, a versão secundária é sempre "1".

  • AUTH_DOMAIN: o domínio usado para autenticar usuários com a API Users. Aplicativos hospedados em appspot.com têm um AUTH_DOMAIN de gmail.com e aceitam qualquer conta do Google. Os aplicativos hospedados em um domínio personalizado têm um AUTH_DOMAIN igual ao domínio personalizado.

  • INSTANCE_ID: contém o ID da instância de front-end que gerencia uma solicitação. O ID é uma string hexadecimal (por exemplo, 00c61b117c7f7fd0ce9e1325a04b8f0df30deaaf). Um administrador conectado pode usar o ID em um URL: https://INSTANCE_ID-dot-VERSION_ID-dot-SERVICE_ID-dot-PROJECT_ID.REGION_ID.r.appspot.com. A solicitação será encaminhada para essa instância de front-end específica. Se não conseguir processar a solicitação, a instância retornará um 503 imediato.

As seguintes variáveis de ambiente fazem parte dos padrões WSGI e CGI, com comportamento especial no App Engine:

  • SERVER_SOFTWARE: no servidor da Web de desenvolvimento, esse valor é "Development/X.Y", em que "X.Y" é a versão do ambiente de execução. Quando executado no App Engine, esse valor é "Google App Engine/X.Y.Z".

As outras variáveis de ambiente são definidas de acordo com o padrão WSGI ou CGI. Para mais informações sobre essas variáveis, consulte o padrão WSGI ou o padrão CGI (links em inglês), conforme apropriado.

Também é possível definir variáveis de ambiente no arquivo app.yaml:

env_variables:
  DJANGO_SETTINGS_MODULE: 'myapp.settings'

O seguinte gerenciador de solicitação webapp2 exibe todas as variáveis de ambiente visíveis para o aplicativo no navegador:

class PrintEnvironmentHandler(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        for key, value in os.environ.iteritems():
            self.response.out.write(
                "{} = {}\n".format(key, value))

Códigos de solicitação

No momento da solicitação, salve o ID da solicitação, que é exclusivo dela. O ID da solicitação pode ser usado posteriormente para procurar os registros da solicitação no Cloud Logging.

O código de amostra a seguir mostra como receber o código da solicitação no contexto dela:

class RequestIdHandler(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        request_id = os.environ.get('REQUEST_LOG_ID')
        self.response.write(
            'REQUEST_LOG_ID={}'.format(request_id))

Armazenamento em cache do app

O ambiente de execução do Python armazena em cache módulos importados entre solicitações em um único servidor da Web, semelhante a como um aplicativo do Python independente carrega um módulo apenas uma vez, mesmo se o módulo for importado por vários arquivos. Como são módulos, os gerenciadores WSGI são armazenados em cache entre solicitações. Os scripts do gerenciador CGI só são armazenados em cache se fornecerem uma rotina main(). Caso contrário, o script do gerenciador CGI é carregado para cada solicitação.

O armazenamento em cache do app oferece um benefício significativo no tempo de resposta. Recomendamos que todos os scripts de gerenciador CGI usem uma rotina main(), conforme descrito abaixo.

Importações são armazenadas em cache

Para melhorar a eficiência, o servidor da Web mantém módulos importados na memória e não os recarrega ou reavalia em solicitações subsequentes para o mesmo aplicativo no mesmo servidor. A maioria dos módulos não inicializa dados globais, nem tem outros efeitos colaterais quando são importados. Dessa maneira, armazená-los em cache não altera o comportamento do aplicativo.

Se o aplicativo importar um módulo que depende da avaliação do módulo a cada solicitação, o aplicativo precisará acomodar esse comportamento de armazenamento em cache.

Armazenamento em cache de Gerenciadores CGI

Peça para o App Engine armazenar em cache o próprio script do gerenciador CGI, além de módulos importados. Se o script de processamento definir uma função chamada main(), o script e seu respectivo ambiente global serão armazenados em cache como um módulo importado. A primeira solicitação para o script em um determinado servidor da Web avalia o script normalmente. Para solicitações subsequentes, o App Engine chama a função main() no ambiente armazenado em cache.

Para armazenar um script de gerenciador em cache, o App Engine precisa poder chamar main() sem argumentos. Se um script de gerenciador não definir uma função main() ou se a função main() exigir argumentos (que não têm padrões), o App Engine carregará e avaliará todo o script para cada solicitação.

Manter o código Python analisado na memória economiza tempo e possibilita respostas mais rápidas. Armazenar o ambiente global em cache também tem outros possíveis usos:

  • Expressões regulares compiladas. Todas as expressões regulares são analisadas e armazenadas de maneira compilada. Armazene expressões regulares compiladas em variáveis globais e use o armazenamento em cache de app para reutilizar os objetos compilados entre as solicitações.

  • Objetos GqlQuery. A string de consulta GQL é analisada quando o objeto GqlQuery é criado. Reutilizar um objeto GqlQuery com vinculação de parâmetro e o método bind() é mais rápido do que reconstruir o objeto a cada vez. Armazene um objeto GqlQuery com vinculação de parâmetro para os valores em uma variável global e depois reutilize-o vinculando novos valores de parâmetro a cada solicitação.

  • Arquivos de configuração e dados. Se carregar e analisar dados de configuração de um arquivo, o aplicativo poderá reter os dados analisados na memória para evitar ter que recarregar o arquivo a cada solicitação.

O script de gerenciador deve chamar main() quando importado. O App Engine espera que importar o script chame main(). Por isso, o App Engine não o chama ao carregar o gerenciador da solicitação pela primeira vez em um servidor.

O armazenamento em cache do aplicativo com main() fornece uma melhoria significativa no tempo de resposta do gerenciador CGI. Recomendamos isso para todos os aplicativos que usam CGI.