Migrer de Java 8 vers le dernier environnement d'exécution Java

Cette page explique comment migrer des environnements d'exécution Java de la première à la deuxième génération. Pour mettre à jour votre application de deuxième génération afin qu'elle utilise la dernière version compatible de Java, consultez la page Mettre à niveau une application existante.

Java 8 n'est plus compatible depuis le 31 janvier 2024. Vos applications Java 8 existantes continueront à fonctionner et à recevoir du trafic. Toutefois, App Engine peut bloquer le redéploiement des applications qui utilisent des environnements d'exécution après leur date de fin de compatibilité. Nous vous recommandons de migrer vers la dernière version compatible de Java en suivant les instructions de cette page.

La migration vers les environnements d'exécution Java de deuxième génération vous permet d'utiliser des fonctionnalités de langage à jour et de créer des applications plus portables, avec du code idiomatique.

Comprendre vos options de migration

Pour réduire la complexité et les efforts liés à la migration, l'environnement standard App Engine vous permet d'accéder à de nombreux services groupés et API anciens, tels que Memcache, dans les environnements d'exécution Java de deuxième génération. Votre application Java peut appeler les API de services groupés via le fichier JAR de l'API App Engine et accéder à la plupart des fonctionnalités de l'environnement d'exécution Java 8.

Vous avez également la possibilité d'utiliser des produits Google Cloud qui offrent des fonctionnalités similaires aux anciens services groupés. Ces produits Google Cloud fournissent des bibliothèques clientes Cloud pour Java idiomatiques. Pour les services groupés qui ne sont pas disponibles séparément dans Google Cloud, tels que le traitement d'image, la recherche et les messages, vous pouvez utiliser des fournisseurs tiers ou d'autres solutions.

Pour en savoir plus sur la migration vers des services non groupés, consultez la section Migrer à partir de services groupés.

La procédure d'exécution de l'environnement d'exécution diffère selon que vous choisissez ou non d'utiliser les anciens services groupés :

Migrer vers les environnements d'exécution Java de deuxième génération avec services groupés Migrer vers les environnements d'exécution Java de deuxième génération sans services groupés
Accédez aux services groupés à l'aide du fichier JAR des API App Engine. Vous pouvez éventuellement utiliser les produits Google Cloud ou les services tiers recommandés.

Utilisez appengine-web.xml et web.xml pour configurer l'application.

Vous devrez peut-être également configurer des fichiers YAML supplémentaires selon les fonctionnalités de votre application.

Utilisez app.yaml pour la configuration de l'application.

Vous devrez peut-être également configurer des fichiers YAML supplémentaires selon les fonctionnalités de votre application.

Les applications sont déployées via Jetty. Utilisez le format WAR pour empaqueter votre application. Les applications sont déployées à l'aide de votre propre serveur. Utilisez le format JAR pour empaqueter votre application. Pour en savoir plus sur la conversion de votre fichier WAR existant en fichier JAR exécutable, consultez la section Réempaqueter un fichier WAR.

Présentation du processus de migration

Voici quelques modifications que vous devrez apporter à votre application App Engine Java 8 et votre processus de déploiement pour utiliser les environnements d'exécution Java de deuxième génération :

Principales différences entre les environnements d'exécution Java 8 et Java de deuxième génération

Voici un récapitulatif des différences entre les environnements d'exécution Java 8 et Java de deuxième génération dans l'environnement standard App Engine :

Environnement d'exécution Java 8 Environnements d'exécution Java de deuxième génération
Déploiement de serveur Serveur déployé pour vous à l'aide de Jetty Si votre application n'utilise pas les anciens services groupés, vous devez déployer un serveur vous-même1.
Anciens services groupés App Engine Fourni Fourni
Utiliser les bibliothèques clientes Cloud pour Java Oui Oui
Extensions de langages et compatibilité avec la bibliothèque système Oui Oui
Accès au réseau externe Oui Oui
Accès au système de fichiers Accès en lecture/écriture à /tmp Accès en lecture/écriture à /tmp
Environnement d'exécution du langage Modifié pour App Engine Environnement d'exécution Open Source non modifié
Mécanisme d'isolation Bac à sable de conteneur basé sur gVisor Bac à sable de conteneur basé sur gVisor
Tester avec un serveur de développement local Compatible Compatible
Configuration de la sécurité des threads (thread safety) Peut être spécifiée dans le fichier appengine-web.xml. Ne peut pas être spécifiée dans les fichiers de configuration. Toutes les applications sont supposées être "thread-safe" (à thread sécurisé)3.
Logging Utilise un paramètre java.util.logging.
ConsoleHandler, qui écrit dans
stderr et vide le flux
après chaque enregistrement.
Cloud Logging standard2
Compatibilité avec le plug-in DataNucleus 2.x Compatible Non compatible 4

Remarques :

  1. Si votre application n'utilise pas les anciens services groupés, les environnements d'exécution Java de deuxième génération peuvent exécuter n'importe quel framework Java tant que vous empaquetez un serveur Web configuré pour répondre aux requêtes HTTP sur le port spécifié par la variable d'environnement PORT (recommandée) ou sur le port 8080. Par exemple, les environnements d'exécution Java de deuxième génération peuvent exécuter un fichier JAR Spring Boot Uber tel quel. Pour plus d'exemples, consultez la section Flexibilité du framework.

    Si votre application utilise les anciens services groupés, App Engine la déploie à l'aide de Jetty de la même manière que dans l'environnement d'exécution Java 8.

  2. La journalisation dans les environnements d'exécution Java de deuxième génération suit la norme de journalisation de Cloud Logging. Dans les environnements d'exécution Java de deuxième génération, les journaux d'applications ne sont plus groupés avec les journaux de requêtes, mais sont séparés dans des enregistrements différents. Pour en savoir plus sur la lecture et l'écriture de journaux dans les environnements d'exécution Java de deuxième génération, consultez le guide de journalisation.

  3. Pour configurer une application non thread-safe dans l'environnement d'exécution Java de deuxième génération, de la même manière qu'avec la définition de <threadsafe>false</threadsafe> dans Java 8, définissez la simultanéité maximale sur 1 dans votre fichier app.yaml, ou dans le fichier appengine-web.xml si vous utilisez les anciens services groupés.

  4. Google ne prend pas en charge la bibliothèque DataNucleus dans les environnements d'exécution de deuxième génération. Les versions plus récentes de DataNucleus présentent une incompatibilité ascendante avec les versions utilisées dans Java 8. Pour accéder à Datastore, nous vous recommandons d'utiliser la bibliothèque cliente en mode Datastore ou la solution Java Objectify (version 6 ou ultérieure). Objectify est une API Open Source pour Datastore qui fournit un niveau d'abstraction plus élevé.

Différences d'utilisation de la mémoire

Les environnements d'exécution de deuxième génération présentent une utilisation de référence de la mémoire plus élevée que les environnements d'exécution de première génération. Cela est dû à plusieurs facteurs, tels que les différentes versions d'image de base et les différences dans la manière dont les deux générations calculent l'utilisation de la mémoire.

Dans les environnements d'exécution de deuxième génération, l'utilisation de la mémoire des instances est calculée comme la somme de la mémoire utilisée par un processus d'application et du nombre de fichiers d'application mis en cache de manière dynamique en mémoire. Pour éviter que les applications qui utilisent beaucoup de mémoire ne provoquent des arrêts d'instance en raison du dépassement des limites de mémoire, effectuez une mise à niveau vers une classe d'instance plus grande avec plus de mémoire.

Différences d'utilisation du processeur

Les environnements d'exécution de deuxième génération peuvent constater une utilisation de référence plus élevée lors du démarrage à froid de l'instance. Selon la configuration du scaling d'une application, cela peut avoir des effets secondaires inattendus, tels qu'un nombre d'instances plus élevé que prévu si une application est configurée pour évoluer en fonction de l'utilisation du processeur. Pour éviter ce problème, examinez et testez les configurations de scaling des applications pour vous assurer que le nombre d'instances est acceptable.

Différences au niveau des en-têtes de requête

Les environnements d'exécution de première génération permettent de transmettre à l'application des en-têtes de requêtes comportant des traits de soulignement (par exemple, X-Test-Foo_bar). Les environnements d'exécution de deuxième génération introduisent Nginx dans l'architecture hôte. Suite à cette modification, les environnements d'exécution de deuxième génération sont configurés pour supprimer automatiquement les en-têtes comportant des traits de soulignement (_). Pour éviter les problèmes liés à l'application, évitez d'utiliser des traits de soulignement dans les en-têtes de requête de l'application.

Souplesse du framework

Les environnements d'exécution Java de deuxième génération n'incluent aucun framework de diffusion Web, sauf si vous utilisez les anciens services groupés. Cela signifie que vous pouvez utiliser un framework autre qu'un framework basé sur un servlet. Si vous utilisez les anciens services groupés, les environnements d'exécution Java de deuxième génération fournissent le framework de diffusion Web Jetty.

Le dépôt Google Cloud GitHub contient des exemples hello world utilisant des frameworks Web Java populaires :

Migrer des fichiers XML vers le format YAML

gcloud CLI n'accepte pas les formats de fichier suivants :

  • cron.xml
  • datastore-index.xml
  • dispatch.xml
  • queue.xml

Les exemples suivants montrent comment migrer vos fichiers xml vers des fichiers yaml.

Migrer automatiquement des fichiers

Pour migrer vos fichiers xml automatiquement :

  1. Vous devez disposer de gcloud CLI en version 226.0.0 ou ultérieure. Pour effectuer la mise à jour vers la dernière version :

    gcloud components update
    
  2. Pour chaque fichier que vous souhaitez migrer, spécifiez l'une des sous-commandes suivantes (cron-xml-to-yaml, datastore-indexes-xml-to-yaml, dispatch-xml-to-yaml, queue-xml-to-yaml) et le nom du fichier :

    gcloud beta app migrate-config queue-xml-to-yaml MY-QUEUE-XML-FILE.xml
    
  3. Revérifiez manuellement le fichier converti avant de le déployer en production.

    Pour voir un exemple de conversion réussie de fichier xml en yaml, consultez les onglets de la section Migrer manuellement des fichiers.

Migrer manuellement des fichiers

Pour migrer manuellement des fichiers xml vers le format yaml :

cron.yaml

Créez un fichier cron.yaml avec un objet cron contenant une liste d'objets, chacun avec des champs correspondant à chacun des attributs de tag <cron> de votre fichier cron.xml, comme indiqué ci-dessous.

Fichier cron.yaml converti :

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'

Fichier cron.xml d'origine :

<?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>

Pour plus d'informations, consultez la documentation de référence de cron.yaml.

dispatch.yaml

Créez un fichier dispatch.yaml avec un objet dispatch contenant une liste d'objets, chacun avec des champs correspondant à chacun des attributs de tag <dispatch> de votre fichier dispatch.xml, comme indiqué ci-dessous.

Fichier dispatch.yaml converti :

dispatch:
- url: '*/favicon.ico'
  module: default
- url: 'simple-sample.uc.r.appspot.com/'
  module: default
- url: '*/mobile/*'
  module: mobile-frontend

Fichier dispatch.xml d'origine

<?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>

Pour plus d'informations, consultez la documentation de référence de dispatch.yaml.

index.yaml

Créez un fichier index.yaml avec un objet indexes contenant une liste d'objets, chacun avec des champs correspondant à chacun des attributs de tag <datastore-index> de votre fichier datastore-indexes.xml, comme indiqué ci-dessous.

Fichier index.yaml converti :

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

Fichier datastore-index.xml d'origine :

<?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>

Pour plus d'informations, consultez la documentation de référence de index.yaml.

queue.yaml

Créez un fichier queue.yaml avec un objet queue contenant une liste d'objets, chacun avec des champs correspondant à chacun des attributs de tag <queue> de votre fichier queue.xml, comme indiqué ci-dessous.

Fichier queue.yaml converti :

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

Fichier queue.xml d'origine :

<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>