Nesta página, você verá instruções para migrar ambientes de execução do Java da primeira para a segunda geração. Para fazer upgrade do aplicativo de segunda geração para usar a versão compatível mais recente do Java, consulte Fazer upgrade de um aplicativo existente.
O Java 8 chegou ao fim do suporte em 31 de janeiro de 2024. Os aplicativos Java 8 atuais continuarão a ser executados e recebendo tráfego. No entanto, o App Engine pode bloquear a reimplantação de aplicativos que usam ambientes de execução após o término da data de suporte. Recomendamos que você migre para a versão compatível mais recente do Java seguindo as diretrizes nesta página.
A migração para os ambientes de execução Java de segunda geração permite usar recursos de linguagem atualizados e criar aplicativos mais portáteis, com código idiomático.
Noções básicas sobre opções de migração
Para reduzir o esforço e a complexidade de migração do ambiente de execução, o ambiente padrão do App Engine permite acessar muitos serviços e APIs em pacote legados, como Memcache, nos ambientes de execução Java de segunda geração. O aplicativo Java pode chamar as APIs de serviços em pacote por meio do JAR da API do App Engine e acessar a maioria das mesmas funcionalidades no ambiente de execução do Java 8.
Você também tem a opção de usar produtos do Google Cloud que oferecem funcionalidades semelhantes aos serviços incluídos legados. Esses produtos do Google Cloud oferecem bibliotecas de cliente do Cloud para Java. Para os serviços incluídos que não estão disponíveis como produtos separados no Google Cloud, como processamento de imagens, pesquisa e mensagens, use provedores de terceiros ou outras soluções alternativas.
Para saber mais sobre como migrar para serviços desagrupados, consulte Como migrar de serviços incluídos.
Há algumas diferenças na maneira de executar a migração do ambiente de execução, dependendo de você optar por usar ou não os serviços incluídos legados:
Como migrar para os tempos de execução Java de segunda geração com serviços agrupados | Como migrar para os tempos de execução Java de segunda geração sem serviços empacotados |
---|---|
Acesse os serviços incluídos usando o JAR das APIs do App Engine. | Opcionalmente, use os produtos do Google Cloud recomendados ou serviços de terceiros. |
Use
Também pode ser necessário configurar outros arquivos YAML, dependendo dos recursos usados pelo app. |
Use
Pode ser necessário configurar outros arquivos YAML, dependendo dos recursos usados pelo app. |
Os apps são implantados via Jetty. Use o formato WAR para empacotar seu aplicativo. | Os aplicativos são implantados usando seu próprio servidor. Use o formato JAR para empacotar o aplicativo. Para saber mais sobre como converter o arquivo WAR existente para um JAR executável, consulte Como reempacotar um arquivo WAR. |
Visão geral do processo de migração
Confira a seguir algumas alterações que talvez você precise fazer no aplicativo Java 8 do App Engine existente e no processo de implantação para usar os ambientes de execução do Java de segunda geração:
- Faça o download da Google Cloud CLI.
- Migre do plug-in autônomo do Maven do App Engine para o plug-in Maven baseado na CLI gcloud ou o plug-in do Gradle baseado na CLI gcloud.
- Instale o JAR da API do App Engine se você estiver usando os serviços agrupados legados.
Principais diferenças entre o Java 8 e os tempos de execução Java de segunda geração
Veja a seguir um resumo das diferenças entre o Java 8 e os tempos de execução do Java de segunda geração no ambiente padrão do App Engine:
Ambiente de execução do Java 8 | Tempos de execução Java de segunda geração | |
---|---|---|
Implantação do servidor | Servidor implantado para você usando Jetty | Se o app não usa os serviços incluídos no pacote, é preciso implantar um servidor por conta própria.1 |
Serviços agrupados do App Engine legado | Fornecido | Fornecido |
Capacidade de usar bibliotecas de cliente do Cloud para Java | Sim | Sim |
Extensão de linguagem e suporte à biblioteca do sistema | Sim | Sim |
Acesso à rede externa | Sim | Sim |
Acesso ao sistema de arquivos | Acesso de leitura/gravação a /tmp
|
Acesso de leitura/gravação a /tmp
|
Ambiente de execução da linguagem | Modificado para o App Engine | Ambiente de execução de código aberto não modificado |
Mecanismo de isolamento | Sandbox de contêiner com base em gVisor | Sandbox de contêiner com base em gVisor |
Como testar com o servidor de desenvolvimento local | Compatível | Compatível |
Configuração de concorrência segura | Pode ser especificado no arquivo appengine-web.xml .
|
Não pode ser especificado nos arquivos de configuração. Consideramos que todos os apps são thread-safe.3 |
Geração de registros | Usa uma java.util.logging. ConsoleHandler , que grava em stderr e limpa o stream após cada registro. |
Cloud Logging padrão 2 |
Suporte ao plug-in DataNucleus 2.x | Compatível | Não compatível 4 |
Observações:
Se o aplicativo não estiver usando serviços em pacote legados, os ambientes de execução do Java de segunda geração poderão executar qualquer framework Java, desde que você empacote um servidor da Web configurado para responder a solicitações HTTP na porta especificada pela variável de ambiente
PORT
(recomendado) ou na porta 8080. Por exemplo, os ambientes de execução do Java de segunda geração podem executar um Uber JAR do Spring Boot como estão. Para mais exemplos, consulte a seção Flexibilidade do framework.Se seu aplicativo estiver usando serviços em pacote legados, o App Engine o implantará usando o Jetty da mesma forma que no ambiente de execução do Java 8.
A geração de registros nos ambientes de execução do Java de segunda geração segue o padrão de geração de registros no Cloud Logging. Nos ambientes de execução do Java de segunda geração, os registros de apps não são mais agrupados com os registros de solicitação, mas são separados em registros diferentes. Para saber mais sobre como ler e gravar registros nos ambientes de execução do Java de segunda geração, consulte o guia de geração de registros.
Para configurar um app não thread-safe no ambiente de execução do Java 11 de segunda geração, semelhante à definição de
<threadsafe>false</threadsafe>
no Java 8, defina a simultaneidade máxima como 1 em qualquer um dos arquivosapp.yaml
ouappengine-web.xml
se estiver usando os serviços agrupados legados.O Google não oferece suporte à biblioteca do DataNucleus nos ambientes de execução de segunda geração. As versões mais recentes do DataNucleus são incompatíveis com versões anteriores usadas no Java 8. Para acessar o Datastore, recomendamos que você use a biblioteca de cliente do modo Datastore ou a solução Objectify (versão 6 ou mais recente) em Java. A Objectify é uma API de código aberto para o Datastore que oferece um nível maior de abstração.
Diferenças de uso da memória
Os ambientes de execução de segunda geração têm um valor de referência maior do uso de memória em comparação com os da primeira geração. Isso ocorre devido a vários fatores, como versões diferentes da imagem de base e diferenças na forma como as duas gerações calculam o uso de memória.
Os ambientes de execução de segunda geração calculam o uso de memória da instância como a soma do que um processo do aplicativo usa e o número de arquivos de aplicativos armazenados em cache dinamicamente na memória. Para evitar que aplicativos com uso intensivo de memória tenham encerramentos de instâncias por excederem os limites de memória, faça upgrade para uma classe de instância maior com mais memória.
Diferenças de uso da CPU
Os ambientes de execução de segunda geração podem ter um valor de referência mais alto de uso da CPU durante a inicialização a frio da instância. Dependendo da configuração de escalonamento de um aplicativo, isso pode ter efeitos colaterais não intencionais, como uma contagem de instâncias maior do que o previsto se um aplicativo estiver configurado para escalonar com base na utilização da CPU. Para evitar esse problema, revise e teste as configurações de escalonamento do aplicativo para garantir que o número de instâncias seja aceitável.
Diferenças de cabeçalhos de solicitação
Os ambientes de execução de primeira geração permitem que os cabeçalhos das solicitações com sublinhados
(por exemplo, X-Test-Foo_bar
) sejam encaminhados para o aplicativo. Os ambientes
de execução de segunda geração introduzem o Nginx na arquitetura do host. Como resultado dessa
mudança, os ambientes de execução de segunda geração são configurados para remover
automaticamente cabeçalhos com sublinhados (_
). Para evitar problemas no aplicativo, evite usar
sublinhados nos cabeçalhos das solicitações.
Flexibilidade do framework
Os ambientes de execução do Java de segunda geração não incluem nenhum framework de veiculação na Web, a menos que você esteja usando os serviços incluídos legados. Isso significa que você pode usar um framework diferente do baseado em servlet. Se você estiver usando os serviços incluídos legados, os ambientes de execução do Java de segunda geração fornecem o framework de veiculação na Web do Jetty.
Há amostras de hello world
que usam os conhecidos frameworks da Web em Java no
repositório do GitHub do Google Cloud:
Como migrar formatos de arquivo XML para YAML
A CLI gcloud não suporta os seguintes formatos de arquivo:
cron.xml
datastore-index.xml
dispatch.xml
queue.xml
Os exemplos a seguir demonstram como migrar seus arquivos xml
para yaml
.
Como migrar arquivos automaticamente
Para migrar seus arquivos xml
automaticamente:
É preciso ter a CLI gcloud versão 226.0.0 ou mais recente. Se quiser atualizar para a versão mais recente:
gcloud components update
Para cada arquivo que você quer migrar, especifique um dos seguintes subcomandos (
cron-xml-to-yaml
,datastore-indexes-xml-to-yaml
,dispatch-xml-to-yaml
,queue-xml-to-yaml
) e o nome do arquivo:gcloud beta app migrate-config queue-xml-to-yaml MY-QUEUE-XML-FILE.xml
Verifique mais uma vez manualmente o arquivo convertido antes de implantar no ambiente de produção.
Para uma amostra de conversão de arquivo
xml
emyaml
, consulte as guias em Como migrar seus arquivos manualmente.
Como migrar arquivos manualmente
Para migrar manualmente seus arquivos xml
para yaml
:
cron.yaml
Crie um arquivo cron.yaml
com um objeto cron
que contenha uma lista de objetos, cada um com campos que correspondem a cada um dos atributos de tag <cron>
no seu arquivo cron.xml
, conforme mostrado abaixo.
Arquivo cron.yaml
convertido:
cron:
- url: '/recache'
schedule: 'every 2 minutes'
description: 'Repopulate the cache every 2 minutes'
- url: '/weeklyreport'
schedule: 'every monday 08:30'
target: 'version-2'
timezone: 'America/New_York'
description: 'Mail out a weekly report'
Arquivo cron.xml
original
<?xml version="1.0" encoding="UTF-8"?>
<cronentries>
<cron>
<url>/recache</url>
<description>Repopulate the cache every 2 minutes</description>
<schedule>every 2 minutes</schedule>
</cron>
<cron>
<url>/weeklyreport</url>
<description>Mail out a weekly report</description>
<schedule>every monday 08:30</schedule>
<timezone>America/New_York</timezone>
<target>version-2</target>
</cron>
</cronentries>
Para mais informações, consulte a documentação de referência do
cron.yaml
.
dispatch.yaml
Crie um arquivo dispatch.yaml
com um objeto dispatch
que contenha uma lista de objetos, cada um com campos que correspondem a cada um dos atributos de tag <dispatch>
no seu arquivo dispatch.xml
, conforme mostrado abaixo.
Arquivo dispatch.yaml
convertido:
dispatch:
- url: '*/favicon.ico'
module: default
- url: 'simple-sample.uc.r.appspot.com/'
module: default
- url: '*/mobile/*'
module: mobile-frontend
Arquivo dispatch.xml
original
<?xml version="1.0" encoding="UTF-8"?>
<dispatch-entries>
<dispatch>
<url>*/favicon.ico</url>
<module>default</module>
</dispatch>
<dispatch>
<url>simple-sample.uc.r.appspot.com/</url>
<module>default</module>
</dispatch>
<dispatch>
<url>*/mobile/*</url>
<module>mobile-frontend</module>
</dispatch>
</dispatch-entries>
Para mais informações, consulte a documentação de referência do
dispatch.yaml
.
index.yaml
Crie um arquivo index.yaml
com um objeto indexes
contendo uma lista de objetos, cada um com campos que correspondem a cada um dos atributos de tag <datastore-index>
no seu arquivo datastore-indexes.xml
, conforme mostrado abaixo.
Arquivo index.yaml
convertido:
indexes:
- ancestor: false
kind: Employee
properties:
- direction: asc
name: lastName
- direction: desc
name: hireDate
- ancestor: false
kind: Project
properties:
- direction: asc
name: dueDate
- direction: desc
name: cost
Arquivo datastore-index.xml
original
<?xml version="1.0" encoding="utf-8"?>
<datastore-indexes
autoGenerate="true">
<datastore-index kind="Employee" ancestor="false">
<property name="lastName" direction="asc" />
<property name="hireDate" direction="desc" />
</datastore-index>
<datastore-index kind="Project" ancestor="false">
<property name="dueDate" direction="asc" />
<property name="cost" direction="desc" />
</datastore-index>
</datastore-indexes>
Para mais informações, consulte a documentação de referência do
index.yaml
.
queue.yaml
Crie um arquivo queue.yaml
com um objeto queue
que contenha uma lista de objetos, cada um com campos que correspondem a cada um dos atributos de tag <queue>
no seu arquivo queue.xml
, conforme mostrado abaixo.
Arquivo queue.yaml
convertido:
queue:
- name: fooqueue
mode: push
rate: 1/s
retry_parameters:
task_retry_limit: 7
task_age_limit: 2d
- name: barqueue
mode: push
rate: 1/s
retry_parameters:
min_backoff_seconds: 10
max_backoff_seconds: 200
max_doublings: 0
Arquivo queue.xml
original
<queue-entries>
<queue>
<name>fooqueue</name>
<rate>1/s</rate>
<retry-parameters>
<task-retry-limit>7</task-retry-limit>
<task-age-limit>2d</task-age-limit>
</retry-parameters>
</queue>
<queue>
<name>barqueue</name>
<rate>1/s</rate>
<retry-parameters>
<min-backoff-seconds>10</min-backoff-seconds>
<max-backoff-seconds>200</max-backoff-seconds>
<max-doublings>0</max-doublings>
</retry-parameters>
</queue>
<queue-entries>