En esta página, se abordan las instrucciones para migrar de los entornos de ejecución de Java de primera generación a la segunda. Si quieres actualizar tu app de segunda generación para usar la última versión compatible de Java, consulta Actualiza una aplicación existente.
Java 8 llegó al fin de la asistencia el 31 de enero de 2024. Tus aplicaciones existentes de Java 8 continuarán ejecutándose y recibiendo tráfico. Sin embargo, App Engine podría bloquear la reimplementación de aplicaciones que usan entornos de ejecución después de la fecha de finalización de la asistencia. Te recomendamos que migres a la versión más reciente compatible de Java con los lineamientos de esta página.
La migración a los entornos de ejecución de Java de segunda generación te permite usar funciones de lenguaje actualizadas y compilar aplicaciones más portátiles, con código idiomático.
Conoce las opciones de migración
Para reducir el esfuerzo y la complejidad del proceso de migración del entorno de ejecución, el entorno estándar de App Engine te permite acceder a muchos de los servicios y APIs agrupados en paquetes heredados, como Memcache, en los entornos de ejecución de Java de segunda generación. Tu aplicación de Java puede llamar a las API de servicios agrupadas a través del archivo JAR de la API de App Engine y acceder a la misma funcionalidad que en el entorno de ejecución de Java 8.
También tienes la opción de usar productos de Google Cloud que ofrecen funciones similares a las de los servicios agrupados en paquetes heredados. Estos productos de Google Cloud proporcionan bibliotecas cliente de Cloud para Java. Para los servicios en paquetes que no están disponibles como productos separados en Google Cloud, como procesamiento de imágenes, búsqueda y mensajería, puedes usar proveedores de terceros o algunas otras soluciones.
Para obtener más información sobre la migración a servicios sin agrupar, consulta Migra desde servicios en paquetes.
Existen algunas diferencias en la forma de realizar la migración del entorno de ejecución, que depende de si eliges usar los servicios agrupados en paquetes heredados:
Migra a los entornos de ejecución de Java de segunda generación con servicios en paquetes | Migra a los entornos de ejecución de Java de segunda generación sin servicios en paquetes |
---|---|
Accede a los paquetes de servicios mediante el JAR de las API de App Engine. | De manera opcional, usa productos recomendados de Google Cloud o servicios de terceros. |
Usa Es posible que también debas configurar archivos YAML adicionales según las características que use tu app. |
Usa Es posible que también debas configurar archivos YAML adicionales según las características que use tu app. |
Las aplicaciones se implementan a través de Jetty. Usa el formato WAR para empaquetar tu app. | Las apps se implementan con tu propio servidor. Usa el formato JAR para empaquetar tu app. Para obtener más información sobre cómo convertir tu archivo WAR existente en un JAR ejecutable, consulta Vuelve a empaquetar un archivo WAR. |
Descripción general del proceso de migración
A continuación, se enumeran algunos cambios que puede que tengas que realizar en tu app existente de App Engine para Java 8 y tu proceso de implementación a fin de usar los entornos de ejecución de segunda generación de Java:
- Descarga Google Cloud CLI.
- Migra del complemento independiente de Maven para App Engine al complemento de Maven basado en la CLI de gcloud o al complemento de Gradle basado en la CLI de gcloud.
- Instala el JAR de la API de App Engine si usas los servicios agrupados en paquetes heredados.
Diferencias clave entre los entornos de ejecución de Java 8 y los de segunda generación
El siguiente es un resumen de las diferencias entre los entornos de ejecución de Java 8 y los de segunda generación en el entorno estándar de App Engine:
Entorno de ejecución de Java 8 | Entornos de ejecución de Java de segunda generación | |
---|---|---|
Implementación del servidor | Servidor implementado para ti con Jetty | Si la app no usa los servicios agrupados en paquetes heredados, debes implementar un servidor tú mismo.1 |
Servicios en paquetes heredados de App Engine | Proporcionado | Proporcionado |
Capacidad de usar las bibliotecas cliente de Cloud para Java | Sí | Sí |
Extensión del lenguaje y compatibilidad con la biblioteca del sistema | Sí | Sí |
Acceso a la red externa | Sí | Sí |
Acceso al sistema de archivos | Acceso de lectura/escritura a /tmp
|
Acceso de lectura/escritura a /tmp
|
Entorno de ejecución del lenguaje | Modificado para App Engine | Entorno de ejecución de código abierto no modificado |
Mecanismo de aislamiento | Zona de pruebas del contenedor basado en gVisor | Zona de pruebas del contenedor basado en gVisor |
Realiza pruebas con el servidor de desarrollo local | Admitido | Admitido |
Configuración de seguridad de los subprocesos | Se puede especificar en el archivo appengine-web.xml .
|
No se puede especificar en los archivos de configuración. Se presume que todas las apps cuentan con protección de subprocesos.3 |
Logging | Usa un java.util.logging. ConsoleHandler , que escribe en stderr y limpia la transmisión después de cada registro. |
Cloud Logging estándar2 |
Compatibilidad con el complemento DataNucleus 2.x | Admitido | No admitido 4 |
Notas:
Si tu app no usa servicios agrupados en paquetes heredados, el entorno de ejecución de Java de segunda generación puede ejecutar cualquier framework de Java, siempre que empaquetes un servidor web configurado para responder a las solicitudes HTTP en el puerto que especifica la variable de entorno
PORT
(recomendado) o en el puerto 8080. Por ejemplo, los entornos de ejecución de Java de segunda generación pueden ejecutar un Boot Uber de Spring Boot tal como está. Para obtener más ejemplos, consulta la sección Flexibilidad del framework.Si tu aplicación usa los servicios agrupados en paquetes heredados, App Engine la implementa mediante el uso de Jetty de la misma manera que en el entorno de ejecución de Java 8.
El registro en los entornos de ejecución de Java de segunda generación sigue el estándar de registro de Cloud Logging. En el entorno de ejecución de Java de segunda generación, los registros de la app ya no se empaquetan con los registros de solicitud, sino que están separados en registros diferentes. Para obtener más información sobre cómo leer y escribir registros en los entornos de ejecución de Java de segunda generación, consulta la guía de registro.
Para configurar una app que no sea segura en los subprocesos en el entorno de ejecución de Java de segunda generación, de manera similar a la configuración de
<threadsafe>false</threadsafe>
en Java 8, establece la simultaneidad máxima en 1 en tu archivoapp.yaml
oappengine-web.xml
si usas los servicios en paquetes heredados.Google no admite la biblioteca de DataNucleus en los entornos de ejecución de segunda generación. Las versiones más recientes de DataNucleus no son compatibles con las versiones usadas en Java 8. Para acceder a Datastore, te recomendamos usar la biblioteca cliente en modo Datastore o la solución Objectify de Java (versión 6 o posterior). Objectify es una API de código abierto para Datastore que proporciona un nivel de abstracción superior.
Diferencias en el uso de memoria
Los entornos de ejecución de segunda generación ven un modelo de referencia de uso de memoria más alto en comparación con los entornos de ejecución de primera generación. Esto se debe a varios factores, como las diferentes versiones de imagen base, y las diferencias en la forma en que las dos generaciones calculan el uso de memoria.
Los entornos de ejecución de segunda generación calculan el uso de memoria de las instancias como la suma de lo que usa un proceso de la aplicación y la cantidad de archivos de la aplicación almacenados en caché de forma dinámica en la memoria. Para evitar que las aplicaciones con uso intensivo de memoria experimenten apagados de instancias debido a que se excedieron los límites de memoria, actualiza a una clase de instancia más grande con más memoria.
Diferencias en el uso de CPU
Los entornos de ejecución de segunda generación pueden ver un modelo de referencia de uso de CPU más alto cuando se inicia en frío en la instancia. Según la configuración de escalamiento de una aplicación, esto puede tener efectos secundarios no deseados, como un recuento de instancias más alto de lo previsto si una aplicación está configurada para escalar en función del uso de CPU. Para evitar este problema, revisa y prueba las configuraciones de escalamiento de la aplicación para asegurarte de que la cantidad de instancias sea aceptable.
Diferencias en el encabezado de la solicitud
Los entornos de ejecución de primera generación permiten que los encabezados de la solicitud con guiones bajos
(p.ej., X-Test-Foo_bar
) se reenvíen a la aplicación. Los entornos de ejecución
de segunda generación ingresan Nginx en la arquitectura del host. Como resultado de este
cambio, los entornos de ejecución de segunda generación están configurados para quitar de forma automática
los encabezados con guiones bajos (_
). Para evitar problemas con la aplicación, evita usar
guiones bajos en los encabezados de la solicitud de la aplicación.
Flexibilidad del framework
Los entornos de ejecución de Java de segunda generación no incluyen ningún framework de entrega web a menos que uses los servicios agrupados en paquetes heredados. Esto significa que puedes usar un framework que no sea uno basado en servlets. Si usas los servicios agrupados en paquetes heredados, los entornos de ejecución de Java de segunda generación proporcionan el framework de entrega web de Jetty.
Hay muestras de hello world
que usan frameworks web populares de Java en el repositorio de GitHub de Google Cloud:
Migra formatos de archivo XML a YAML
La CLI de gcloud no admite los siguientes formatos de archivo:
cron.xml
datastore-index.xml
dispatch.xml
queue.xml
Los siguientes ejemplos demuestran cómo migrar tus archivos xml
a archivos yaml
.
Migra tus archivos de forma automática
Para migrar tus archivos xml
de forma automática, sigue estos pasos:
Debes tener la versión 226.0.0 de la CLI de gcloud o una posterior. Para actualizar a la última versión, haz lo siguiente:
gcloud components update
Para cada archivo que desees migrar, especifica uno de los siguientes subcomandos (
cron-xml-to-yaml
,datastore-indexes-xml-to-yaml
,dispatch-xml-to-yaml
,queue-xml-to-yaml
) y el nombre del archivo:gcloud beta app migrate-config queue-xml-to-yaml MY-QUEUE-XML-FILE.xml
Realiza una doble comprobación del archivo convertido antes de realizar la implementación en producción.
Para obtener una conversión de muestra exitosa de un archivo
xml
a un archivoyaml
, consulta las pestañas Migra los archivos de forma manual.
Migra tus archivos de forma manual
Para migrar de forma manual tus archivos xml
a archivos yaml
, haz lo siguiente:
cron.yaml
Crea un archivo cron.yaml
con un objeto cron
que contenga una lista de objetos, cada uno con campos que correspondan a cada uno de los atributos de la etiqueta <cron>
en tu archivo cron.xml
, como se muestra a continuación.
Archivo 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'
Archivo 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 obtener más información, consulta la documentación de referencia de cron.yaml
.
dispatch.yaml
Crea un archivo dispatch.yaml
con un objeto dispatch
que contenga una lista de objetos, cada uno con campos que correspondan a cada uno de los atributos de la etiqueta <dispatch>
en tu archivo dispatch.xml
, como se muestra a continuación.
Archivo dispatch.yaml
convertido:
dispatch:
- url: '*/favicon.ico'
module: default
- url: 'simple-sample.uc.r.appspot.com/'
module: default
- url: '*/mobile/*'
module: mobile-frontend
Archivo 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 obtener más información, consulta la documentación de referencia de dispatch.yaml
.
index.yaml
Crea un archivo index.yaml
con un objeto indexes
que contenga una lista de objetos, cada uno con campos que correspondan a cada uno de los atributos de la etiqueta <datastore-index>
en tu archivo datastore-indexes.xml
, como se muestra a continuación.
Archivo 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
Archivo 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 obtener más información, consulta la documentación de referencia de index.yaml
.
queue.yaml
Crea un archivo queue.yaml
con un objeto queue
que contenga una lista de objetos, cada uno con campos que correspondan a cada uno de los atributos de la etiqueta <queue>
en tu archivo queue.xml
, como se muestra a continuación.
Archivo 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
Archivo 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>