My favorites | Português | Sign in

O ambiente de execução do servlet Java

O Google App Engine executa o seu aplicativo da web em Java usando a Java 6 JVM em um ambiente seguro do sandbox. O Google App Engine invoca as classes de servlet do seu aplicativo para manipular solicitações e preparar respostas nesse ambiente.

Como selecionar a versão da API de Java

O Google App Engine sabe usar o ambiente de execução em Java para o seu aplicativo quando você usa a ferramenta AppCfs do SDK para Java para enviar o aplicativo.

No que diz respeito a essa criação, existe apenas uma versão da API do Google App Engine em Java. Essa API é representada pelo appengine-api-*.jar incluído no SDK (em que * representa a versão da API e do SDK). Para selecionar a versão da API que o seu aplicativo usa, inclua esse JAR no diretório WEB-INF/lib/ do aplicativo. Se for lançada uma versão nova do ambiente de execução em Java que apresenta alterações incompatíveis com os aplicativos existentes, esse ambiente receberá um número de versão novo. O seu aplicativo continuará a usar a versão anterior até que você substitua o JAR pela versão nova (de um SDK mais recente) e envie o aplicativo novamente.

Solicitações e servlets

Ao receber uma solicitação da web para o seu aplicativo, o Google App Engine invoca o servlet que corresponde ao URL, como descrito no descritor de implementação do aplicativo (o arquivo web.xml no diretório WEB-INF/). Ele usa a API de servlet Java para fornecer os dados solicitados ao servlet e aceitar os dados da resposta.

O Google App Engine utiliza diversos servidores da web para executar seu aplicativo e ajusta automaticamente o número de servidores sendo usados para manipular as solicitações de forma confiável. Uma determinada solicitação pode ser direcionada a qualquer servidor e este pode não ser o mesmo que manipulou uma solicitação anterior do mesmo usuário.

A classe de servlet do exemplo abaixo exibe uma mensagem simples no navegador do usuário.

import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyServlet extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        resp.setContentType("text/plain");
        resp.getWriter().println("Hello, world");
    }
}

Respostas

O Google App Engine chama o servlet com um objeto de solicitação e um objeto de resposta, e depois espera até que o servlet preencha o objeto de resposta e retorne. Após o retorno do servlet, os dados no objeto de resposta são enviados para o usuário.

O Google App Engine não oferece suporte ao envio de dados para o cliente, à realização de cálculos adicionais no aplicativo e ao envio de dados extras. Em outras palavras, o Google App Engine não oferece suporte à "transmissão" de dados em resposta a uma única solicitação.

Se o cliente envia cabeçalhos HTTP com a solicitação, indicando que o cliente pode aceitar conteúdo compactado (através de gzip), o Google App Engine compacta os dados de resposta automaticamente e anexa os cabeçalhos de resposta apropriados. Os cabeçalhos de solicitação Accept-Encoding e User-Agent são usados para determinar se o cliente pode receber respostas compactadas de forma confiável. Os clientes personalizados podem forçar a compactação do conteúdo, especificando os cabeçalhos Accept-Encoding e User-Agent com valor "gzip".

O temporizador de solicitação

Um manipulador de solicitação tem um período de tempo limitado para gerar e retornar uma resposta para uma solicitação, normalmente em torno de 30 segundos. Assim que o prazo é atingido, o manipulador de solicitação é interrompido.

O ambiente de execução em Java interrompe o servlet gerando uma com.google.apphosting.api.DeadlineExceededException. Se o manipulador de solicitação não identificar essa exceção, assim como com todas as exceções não identificadas, o ambiente de execução retornará ao cliente um erro de servidor HTTP 500.

O manipulador de solicitação pode identificar esse erro e personalizar a resposta. O ambiente de execução dá um pouco mais de tempo (menos de um segundo) depois de emitir a exceção para que o manipulador de solicitação prepare uma resposta personalizada.

Embora uma solicitação possa levar até 30 segundos para responder, o Google App Engine é otimizado para aplicativos com solicitações de vida curta, normalmente para as que levam algumas centenas de milissegundos. Um aplicativo eficiente responde rapidamente a maioria das solicitações. Um aplicativo que não o fizer não escalará bem com a infraestrutura do Google App Engine.

O sandbox

Para permitir que o Google App Engine distribua solicitações para aplicativos em diversos servidores da web e para impedir a interferência de um aplicativo em outro, o aplicativo executa em um ambiente "sandbox" restrito. Neste ambiente, o aplicativo pode executar código, armazenar e consultar dados no armazenamento de dados do Google App Engine, utilizar o e-mail do Google App Engine, obter URL e serviços de usuários e examinar a solicitação de web do usuário e preparar a resposta.

Um aplicativo do Google App Engine não pode:

  • gravar no sistema de arquivos. Os aplicativos devem utilizar o armazenamento de dados do Google App Engine para armazenar dados persistentes. É permitida a leitura do sistema de arquivos e todos os arquivos que foram enviados com o aplicativo estão disponíveis.
  • abrir um soquete ou acessar diretamente outro host. Um aplicativo pode utilizar o serviço de obtenção de URL do Google App Engine para fazer solicitações HTTP e HTTPS para outros hosts nas portas 80 e 443, respectivamente.
  • gerar um subprocesso ou linha. Uma solicitação da web a um aplicativo deve ser manipulada em um único processo, dentro de alguns segundos. Os processos que demoram muito tempo para responder são encerrados, para evitar sobrecarregar o servidor da web.
  • fazer outros tipos de chamadas do sistema.

Linhas

Um aplicativo Java não pode criar uma java.lang.ThreadGroup ou uma java.lang.Thread novas. Essas restrições também são válidas para classes JRE que usam linhas. Por exemplo, um aplicativo não pode criar um java.util.concurrent.ThreadPoolExecutor novo nem um java.util.Timer. Um aplicativo pode realizar operações na linha atual, como Thread.currentThread().dumpStack().

O sistema de arquivos

Um aplicativo Java não pode usar nenhuma classe usada para criar o sistema de arquivos, como java.io.FileWriter. Um aplicativo pode ler os seus próprios arquivos do sistema de arquivos usando classes como java.io.FileReader. Um aplicativo também pode acessar seus próprios arquivos como "recursos", como com Class.getResource() ou ServletContext.getResource().

Somente os arquivos considerados "arquivos de recursos" ficam acessíveis ao aplicativo por meio do sistema de arquivos. Por padrão, todos os arquivos no WAR são "arquivos de recursos". Para excluir arquivos desse conjunto, use o arquivo appengine-web.xml.

java.lang.System

Os recursos da classe java.lang.System não aplicáveis ao Google App Engine são desativados.

Os métodos System a seguir não têm função no Google App Engine: exit(), gc(), runFinalization(), runFinalizersOnExit()

Os seguintes métodos System retornam null: inheritedChannel(), console()

Um aplicativo não pode fornecer nem invocar diretamente nenhum código JNI nativo. Os seguintes métodos System emitem uma java.lang.SecurityException: load(), loadLibrary(), setSecurityManager()

Reflexão

Um aplicativo tem acesso completo, irrestrito e refletivo às suas próprias classes. Ele pode consultar os membros privados, usar java.lang.reflect.AccessibleObject.setAccessible() e ler/definir membros privados.

Um aplicativo também pode refletir em classes JRE e API, como java.lang.String e javax.servlet.http.HttpServletRequest. No entanto, ele pode acessar apenas os membros públicos dessas classes, não os protegidos ou privados.

Um aplicativo não pode refletir quaisquer outras classes que não pertencem a ele mesmo e não pode usar o método setAccessible() para contornar essas restrições.

Carregamento de classe personalizado

O carregamento de classe personalizado é completamente suportado pelo Google App Engine. Fique atento pois o Google App Engine ignora todos os ClassLoaders para atribuir as mesmas permissões a todas as classes carregadas pelo seu aplicativo. Se você realizar um carregamento de classe personalizado, tenha cuidado ao carregar códigos de terceiros não confiáveis.

Lista de classes válidas do JRE

O acesso às classes na biblioteca padrão Java (JRE, o ambiente de execução em Java) está limitado às classes da Lista de classes válidas do JRE do Google App Engine.

Registro

O seu aplicativo pode gravar informações nos registros do aplicativo usando java.util.logging.Logger. Você pode exibir e analisar os dados de registro do seu aplicativo utilizando o Console de administração ou fazer o download utilizando appcfg.sh request_logs. O Console de administração pode reconhecer os níveis de registro da classe Logger e exibir interativamente as mensagens em níveis diferentes.

Tudo o que o servlet grava no fluxo de saída padrão (System.out) e no fluxo de erro padrão (System.err) é capturado pelo Google App Engine e gravado nos registros do aplicativo. As linhas gravadas no fluxo de saída padrão são registradas no nível "INFO" e as linhas gravadas no fluxo de erro padrão são registradas no nível "WARNING". Qualquer estrutura de registro (como log4j) que registra nos fluxos de saída ou de erro funcionará. No entanto, para um controle mais refinado da exibição do nível de registro do Console de administração, a estrutura de registro deve usar um adaptador java.util.logging.

import java.util.logging.Logger;
// ...

public class MyServlet extends HttpServlet {
    private static final Logger log = Logger.getLogger(MyServlet.class.getName());

    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {

        log.info("An informational message.");

        log.warning("A warning message.");

        log.severe("An error message.");
    }
}

O SDK para Java do Google App Engine inclui um arquivo logging.properties de modelo no diretório appengine-java-sdk/config/user/. Para usá-lo copie o arquivo no seu diretório WEB-INF/classes (ou em qualquer outro lugar no WAR) e a propriedade do sistema java.util.logging.config.file em "WEB-INF/classes/logging.properties" (ou em algum outro caminho que você escolher, relativo à raiz do aplicativo). Para definir as propriedades do sistema no arquivo appengine-web.xml:

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
    ...

    <system-properties>
        <property name="java.util.logging.config.file" value="WEB-INF/classes/logging.properties" />
    </system-properties>

</appengine-web-app>

O novo assistente de projetos do plug-in do Google para o Eclipse cria esses arquivos de configuração do registro para você e os copia automaticamente para WEB-INF/classes/. Para usar o java.util.logging, é preciso definir a propriedade do sistema.

O ambiente

Todas as propriedades do sistema e variáveis de ambiente são exclusivas para o seu aplicativo. A definição de uma propriedade do sistema afeta apenas a visualização dessa propriedade no seu aplicativo e não a visualização da JVM.

As propriedades do sistema e as variáveis de ambiente podem ser definidas no descritor de implementação.

O Google App Engine define as seguintes propriedades do sistema ao inicializar a JVM no servidor de um aplicativo:

  • file.separator
  • path.separator
  • line.separator
  • java.version
  • java.vendor
  • java.vendor.url
  • java.class.version
  • java.specification.version
  • java.specification.vendor
  • java.specification.name
  • java.vm.vendor
  • java.vm.name
  • java.vm.specification.version
  • java.vm.specification.vendor
  • java.vm.specification.name
  • user.dir

Cotas e limites

Cada solicitação recebida para o aplicativo é computada para a cota Solicitações.

Os dados recebidos como parte de uma solicitação são computados para a cota Largura de banda de entrada (faturável). Os dados enviados em resposta a uma solicitação são computados para a cota Largura de banda de saída (faturável).

As solicitações HTTP e HTTPS (segura) são computadas para as cotas Solicitações, Largura de banda de entrada (faturável) e Largura de banda de saída (faturável). A página "Quota Details" (Detalhes da cota) do Console de administração também informa Solicitações seguras, Largura de banda de entrada segura e Largura de banda de saída segura como valores separados para informação. Apenas solicitações HTTPS são computadas para esses valores.

O tempo de processamento da CPU gasto com a execução de um manipulador de solicitação é computado para a cota Tempo de CPU (faturável).

Para obter mais informações sobre cotas, consulte Quotas (Cotas) e a seção "Quota Details" (Quota Details) do Console de administração.

Além das cotas, os seguintes limites são aplicados aos manipuladores de solicitação:

Limite Quantidade
tamanho da solicitação 10 megabytes
tamanho da resposta 10 megabytes
duração da solicitação 30 segundos
solicitações dinâmicas simultâneas 30 *
número máximo de arquivos de aplicativo 1.000
número máximo de arquivos estáticos 1.000
tamanho máximo de um arquivo de aplicativo 10 megabytes
tamanho máximo de um arquivo estático 10 megabytes
tamanho máximo total de todos os arquivos de aplicativo e arquivos estáticos 150 megabytes

* Um aplicativo pode processar cerca de 30 solicitações dinâmicas ativas simultaneamente. Isso significa que um aplicativo do qual a média de tempo de processamento de solicitação no servidor é de 75 milissegundos pode atender até (1000 ms/segundo / 75 ms/solicitação) * 30 = 400 solicitações/segundo sem sofrer nenhuma latência adicional. Os aplicativos que são muito limitados pela CPU podem sofrer de latência adicional em solicitações de longa duração de modo a liberar espaço para outros aplicativos que compartilham os mesmos servidores. As solicitações para arquivos estáticos não são afetadas por esse limite.