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.
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.
Caso seu aplicativo use serviços, é possível endereçar solicitações para um serviço específico ou uma determinada versão 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 processa. Para isso, configure o elemento max_concurrent_requests
no arquivo app.yaml.
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!
.
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, isso é limitado pelas 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 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 HTTP quanto as HTTPS (seguras) são contabilizadas 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 Google Cloud também exibe 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 |
Tempo limite da solicitação pendente | 10 segundos |
Tamanho máximo de um campo de cabeçalho de solicitação único | 8 kilobytes para ambientes de execução de segunda geração no ambiente padrão. As solicitações para esses ambientes de execução com campos de cabeçalho acima de 8 kilobytes retornarão erros HTTP 400. |
Limites de solicitações
Todas as solicitações em HTTP/2 são traduzidas para HTTP/1.1 quando encaminhadas para o servidor do aplicativo.
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 legado ou do Cloud Storage.
O limite de cabeçalho de resposta é de 8 KB para ambientes de execução de segunda geração. Os cabeçalhos de resposta que excederem esse limite retornarão erros HTTP 502, com registros que mostram
upstream sent too big header while reading response header from upstream
.
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 retificados por proxies intermediários antes de chegarem ao aplicativo.
Para mais informações, consulte a referência sobre cabeçalhos de solicitação.
Como processar os tempos limites das solicitações
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. Para garantir esse nível de desempenho, há um tempo limite máximo de solicitação tributo pelo sistema para cada aplicativo.
Se o aplicativo exceder esse prazo, o App Engine interromperá o gerenciador de solicitações. O ambiente de execução do Python faz isso gerando uma exceçãoDeadlineExceededError
de 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.
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.
Respostas
O App Engine chama o script do gerenciador com umRequest
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 de tamanho que se aplicam à resposta gerada. Essa resposta pode ser modificada antes de retornar 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
O App Engine faz o possível para exibir conteúdo compactado (gzip) para clientes compatíveis. Para determinar se o conteúdo precisa ser compactado, o App Engine faz o seguinte ao receber uma solicitação:Confirma se o cliente pode receber respostas compactadas de maneira confiável visualizando os cabeçalhos
Accept-Encoding
eUser-Agent
na solicitação. Esse método evita alguns erros conhecidos com conteúdo compactado com gzip nos navegadores mais conhecidos.Confirma se a compactação do conteúdo é apropriada ao visualizar o cabeçalho
Content-Type
configurado para o gerenciador de respostas. Em geral, a compactação é apropriada para tipos de conteúdo baseados em texto, e não para tipos de conteúdo binário.
Observe o seguinte:
Um cliente pode forçar a compactação de tipos de conteúdo baseados em texto definindo os cabeçalhos da solicitação
Accept-Encoding
eUser-Agent
comogzip
.Se uma solicitação não especificar
gzip
no cabeçalhoAccept-Encoding
, o App Engine não compactará os dados de resposta.O Google Frontend armazena em cache as respostas dos gerenciadores de arquivo e diretório estáticos do App Engine. Dependendo de diversos fatores, como qual tipo de dados de resposta é armazenado em cache primeiro, quais cabeçalhos
Vary
são especificados na resposta e quais cabeçalhos estão incluídos na solicitação, o cliente pode solicitar dados compactados e recebê-los não compactados e vice-versa. Para mais informações, consulte Armazenamento de respostas em cache.
Armazenamento de respostas em cache
O Google Frontend e, possivelmente, o navegador do usuário e outros servidores proxy de cache intermediários armazenarão as respostas do aplicativo em cache, conforme instruído pelos cabeçalhos de armazenamento em cache padrão especificados na resposta. Especifique esses cabeçalhos de resposta por meio do framework, diretamente no seu código ou por meio de gerenciadores de diretórios e arquivos estáticos do App Engine.
No Google Frontend, a chave de cache é o URL completo da solicitação.
Como armazenar conteúdo estático em cache
Para garantir que os clientes sempre recebam conteúdo estático atualizado assim que ele
for publicado, recomendamos exibir conteúdo estático de diretórios com
versão, como css/v1/styles.css
. O Google Frontend não validará
o cache (verifique o conteúdo atualizado) até que ele expire. Mesmo após a expiração, ele não será atualizado até que o conteúdo do URL de solicitação seja alterado.
Os seguintes cabeçalhos de resposta que podem ser
definidos em
app.yaml
influenciam como e quando o Google Frontend armazena conteúdo em cache:
Cache-Control
precisa ser definido comopublic
para que o Google Frontend armazene conteúdo em cache. Ele também pode ser armazenado em cache pelo Google Frontend, a menos que você especifique uma diretivaCache-Control
private
ouno-store
. Se você não definir esse cabeçalho emapp.yaml
, o App Engine irá adicioná-lo automaticamente a todas as respostas processadas por um gerenciador de arquivo ou diretório estático. Para mais informações, consulte Cabeçalhos adicionados ou substituídos.Vary
: para permitir que o cache retorne respostas diferentes para um URL com base nos cabeçalhos enviados na solicitação, defina um ou mais dos seguintes valores no cabeçalho da respostaVary
:Accept
,Accept-Encoding
,Origin
ouX-Origin
Devido ao potencial para alta cardinalidade, os dados não serão armazenados em cache para outros valores de
Vary
.Por exemplo:
Especifique o seguinte cabeçalho de resposta:
Vary: Accept-Encoding
O aplicativo recebe uma solicitação que contém o cabeçalho
Accept-Encoding: gzip
. O App Engine retorna uma resposta compactada e o Google Frontend armazena em cache a versão em gzip dos dados da resposta. Todas as solicitações subsequentes deste URL que contenham o cabeçalhoAccept-Encoding: gzip
receberão os dados compactados em gzip do cache até que ele se torne inválido (devido à alteração do conteúdo após a expiração).O aplicativo recebe uma solicitação que não contém o cabeçalho
Accept-Encoding
. O App Engine retorna uma resposta descompactada e o Google Frontend armazena em cache a versão descompactada dos dados de resposta. Todas as solicitações subsequentes deste URL que não contenham o cabeçalhoAccept-Encoding
receberão os dados compactados do cache até que o ele se torne inválido.
Se você não especificar um cabeçalho de resposta
Vary
, o Google Frontend criará uma única entrada de cache para o URL e a usará para todas as solicitações, independentemente dos cabeçalhos na solicitação. Por exemplo:- Você não especifica o cabeçalho de resposta
Vary: Accept-Encoding
. - Uma solicitação contém o cabeçalho
Accept-Encoding: gzip
e a versão compactada em gzip dos dados de resposta será armazenada em cache. - Uma segunda solicitação não contém o cabeçalho
Accept-Encoding: gzip
. No entanto, como o cache contém uma versão compactada em gzip dos dados de resposta, a resposta será compactada, mesmo que o cliente tenha solicitado dados descompactados.
Os cabeçalhos da solicitação também influenciam o armazenamento em cache:
- Se a solicitação contiver um cabeçalho
Authorization
, o conteúdo não será armazenado em cache pelo Google Frontend.
Expiração do cache
Por padrão, os cabeçalhos de armazenamento em cache que gerenciadores de arquivo e diretório estáticos do App Engine adicionam às respostas instruem os clientes e os proxies da Web, como o Google Frontend, a expirar o cache após 10 minutos.
Depois que um arquivo é transmitido com um prazo de validade determinado, geralmente, não há como removê-lo de caches de proxy da Web, mesmo que o usuário limpe seu próprio cache do navegador. A reimplantação de uma nova versão do aplicativo não redefinirá nenhum cache. Portanto, se você planeja modificar um arquivo estático, ele deve ter um tempo de expiração curto (menos de uma hora). Na maioria dos casos, o prazo de validade padrão de 10 minutos é suficiente.
É possível alterar a expiração padrão de todos os gerenciadores de arquivos e diretórios estáticos
especificando o elemento
default_expiration
no
arquivo
app.yaml
. Para definir prazos de validade específicos para
gerenciadores
individuais, especifique o elemento expiration
dentro do elemento do gerenciador no
arquivo
app.yaml
.
O valor especificado no tempo de expiração dos elementos será usado para
definir os cabeçalhos de resposta HTTP Cache-Control
e Expires
.
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 rotinamain()
. 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.
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 umrequest_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 Google 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").
Ambiente
O ambiente de execução define automaticamente muitas variáveis de ambiente. É possível definir mais emapp.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 arquivoapp.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 umAUTH_DOMAIN
degmail.com
e aceitam qualquer conta do Google. Os aplicativos hospedados em um domínio personalizado têm umAUTH_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:
IDs 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:
Como forçar conexões HTTPS
Por motivos de segurança, todos os aplicativos precisam incentivar os clientes a
se conectar por https
. Para instruir o navegador a preferir https
a http
em uma determinada página
ou em todo o domínio, defina o cabeçalho Strict-Transport-Security
nas respostas.
Exemplo:
Strict-Transport-Security: max-age=31536000; includeSubDomains
Para definir esse cabeçalho para qualquer conteúdo estático exibido pelo app, adicione o
cabeçalho aos gerenciadores de arquivos e diretórios
estáticos do app.
Se quiser definir esse cabeçalho para respostas geradas a partir do seu código, use a biblioteca flask-talisman
.
Como gerenciar o trabalho em segundo plano assíncrono
O trabalho em segundo plano é qualquer trabalho que seu aplicativo execute para uma solicitação depois de ter entregado a resposta HTTP. Evite executar trabalhos em segundo plano no aplicativo e revise seu código para verificar se todas as operações assíncronas foram concluídas antes de enviar a resposta.
Para jobs de longa duração, recomendamos o uso do Cloud Tasks. Com o Cloud Tasks, as solicitações HTTP têm longa duração e retornam uma resposta somente após o término de qualquer trabalho assíncrono.