Migrar a Java Runtime 11

La migración al entorno de ejecución de Java 11 te permite usar funciones de lenguaje actualizadas y compilar apps que sean más portátiles, con código idiomático.

Comprende 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 servicios y API del paquete de App Engine en el entorno de ejecución de Java 11, como Memcache. Tu aplicación de Java 11 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 en paquetes de App Engine. 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 en paquetes de App Engine:

Migra a Java 11 con servicios en paquetes Migra a Java 11 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 appengine-web.xml y web.xml para la configuración de la app.

Es posible que también debas configurar archivos YAML adicionales según las características que use tu app.

Usa app.yaml para la configuración de la app.

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 el entorno de ejecución de App Engine Java 11:

Diferencias fundamentales entre los entornos de ejecución de Java 8 y Java 11

El siguiente es un resumen de las diferencias entre los entornos de ejecución de Java 8 y Java 11 en el entorno estándar de App Engine:

Entorno de ejecución de Java 8 Entorno de ejecución de Java 11
Implementación del servidor Servidor implementado para ti a través de Jetty Si tu app no usa los servicios agrupados de App Engine, debes implementar un servidor tú mismo1.
Servicios en paquetes Proporcionado Proporcionado
Capacidad de usar las bibliotecas cliente de Cloud para Java No
Extensión del lenguaje y compatibilidad con la biblioteca del sistema
Acceso a la red externa
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 Patentado Zona de pruebas del contenedor basado en gVisor
Realiza pruebas con el servidor de desarrollo local Admitido Admitido
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

Notas:

  1. Si tu app no usa servicios en paquetes de App Engine, el entorno de ejecución de Java 11 puede ejecutar cualquier framework de Java, siempre que empaquetes un servidor web configurado para responder a las solicitudes HTTP en el puerto que especifica el archivo. La variable de entorno PORT (recomendado) o en el puerto 8080. Por ejemplo, el entorno de ejecución de Java 11 puede ejecutar un uber JAR 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 de App Engine, App Engine la implementa mediante el uso de Jetty de la misma manera que en el entorno de ejecución de Java 8.

  2. El registro en el entorno de ejecución de Java 11 sigue el estándar de registro en Cloud Logging. En el entorno de ejecución de Java 11, los registros de la app ya no se agrupan 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 el entorno de ejecución de Java 11, consulta la guía de registro.

Flexibilidad del framework

El entorno de ejecución de Java 11 no incluye ningún framework de entrega web, lo que significa que ya no estás limitado a los frameworks basados en servlet.

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

El SDK de Cloud 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:

  1. Debes tener la versión 226.0.0 del SDK de Cloud o posterior. Para actualizar a la última versión, haz lo siguiente:

    gcloud components update
    
  2. 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
    
  3. 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 archivo yaml, 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>