Différences entre Java 8 et Java 11+

La migration vers les environnements d'exécution Java 11+, également appelés 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 11+ avec des services groupés Migrer vers les environnements d'exécution Java 11+ 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 11+

Voici un récapitulatif des différences entre les environnements d'exécution Java 8 et Java 11+ dans l'environnement standard App Engine :

Environnement d'exécution Java 8 Environnements d'exécution Java 11+
Déploiement de serveur Serveur déployé pour vous via 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

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.

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>