Java 8 ha raggiunto la fine del supporto il 31 gennaio 2024. Le applicazioni Java 8 esistenti continueranno a essere eseguite e a ricevere traffico. Tuttavia, App Engine potrebbe bloccare il nuovo deployment di applicazioni che utilizzano runtime dopo la data di fine dell'assistenza. Ti consigliamo di eseguire la migrazione all'ultima versione supportata di Java seguendo le linee guida in questa pagina.
La migrazione ai runtime Java 11 e versioni successive, noti anche come runtime Java di seconda generazione, ti consente di utilizzare funzionalità del linguaggio aggiornate e di creare app più portabili, con codice idiomatico.
Informazioni sulle opzioni di migrazione
Per ridurre lo sforzo e la complessità della migrazione del runtime, l'ambiente standard di App Engine ti consente di accedere a molti servizi e API in bundle legacy, come Memcache, nei runtime Java di seconda generazione. L'app Java può chiamare le API dei servizi in bundle tramite il JAR dell'API App Engine e accedere alla maggior parte delle stesse funzionalità del runtime Java 8.
Hai anche la possibilità di utilizzare prodotti Google Cloud che offrono funzionalità simili a quelle dei servizi in bundle legacy. Questi prodotti Google Cloud forniscono librerie client Cloud per Java idiomatiche. Per i servizi in bundle che non sono disponibili come prodotti separati in Google Cloud, ad esempio elaborazione di immagini, ricerca e messaggistica, puoi utilizzare fornitori di terze parti o altre soluzioni alternative.
Per scoprire di più sulla migrazione a servizi non in bundle, consulta Migrazione dai servizi in bundle.
Esistono alcune differenze nel modo in cui esegui la migrazione del runtime, a seconda che tu scelga o meno di utilizzare i servizi in bundle legacy:
Migrazione ai runtime Java 11 e versioni successive con servizi in bundle | Migrazione ai runtime Java 11 e versioni successive senza servizi in bundle |
---|---|
Accedi ai servizi in bundle utilizzando il JAR delle API di App Engine. | Se vuoi, utilizza i prodotti Google Cloud o i servizi di terze parti consigliati. |
Utilizza
Potresti anche dover configurare file YAML aggiuntivi a seconda delle funzionalità utilizzate dalla tua app. |
Utilizza
Potresti anche dover configurare file YAML aggiuntivi a seconda delle funzionalità utilizzate dalla tua app. |
Il deployment delle app viene eseguito tramite Jetty. Usa il formato WAR per pacchettizzare la tua app. | Il deployment delle app viene eseguito utilizzando il tuo server. Utilizza il formato JAR per pacchettizzare l'app. Per scoprire di più sulla conversione del file WAR esistente in un file JAR eseguibile, consulta la pagina relativa alla ripacchettizzazione di un file WAR. |
Panoramica del processo di migrazione
Di seguito sono elencate alcune modifiche che potresti dover apportare all'app Java 8 di App Engine esistente e al processo di deployment per utilizzare i runtime Java di seconda generazione:
- Scarica Google Cloud CLI.
- Esegui la migrazione dal plug-in Maven autonomo di App Engine al plug-in Maven basato su gcloud CLI o al plug-in Gradle basato su gcloud CLI.
- Installa il JAR dell'API App Engine se utilizzi i servizi legacy in bundle.
Esegui la migrazione dei file XML nei file
yaml
equivalenti.
Differenze principali tra i runtime Java 8 e Java 11 e versioni successive
Di seguito è riportato un riepilogo delle differenze tra i runtime Java 8 e Java 11 e versioni successive nell'ambiente standard di App Engine:
Runtime Java 8 | Runtime Java 11 e versioni successive | |
---|---|---|
Deployment del server | Deployment del server per te tramite Jetty | Se la tua app non utilizza i servizi in bundle legacy, devi eseguire il deployment di un server autonomamente.1 |
Servizi in bundle legacy di App Engine | Fornito da Google | Fornito da Google |
Possibilità di utilizzare le librerie client di Cloud per Java | Sì | Sì |
Supporto di estensioni di lingua e librerie di sistema | Sì | Sì |
Accesso alla rete esterna | Sì | Sì |
Accesso al file system | Accesso in lettura/scrittura a /tmp
|
Accesso in lettura/scrittura a /tmp
|
Runtime linguaggio | Modificata per App Engine | Runtime open source non modificato |
Meccanismo di isolamento | Sandbox del container basata su gVisor | Sandbox del container basata su gVisor |
Test con il server di sviluppo locale | Supportato | Supportato |
Configurazione di Thread Safety | Può essere specificato nel file appengine-web.xml .
|
Non può essere specificato nei file di configurazione. Tutte le app sono presunte essere thread-safe.3 |
Logging | Utilizza un valore java.util.logging. ConsoleHandler , che scrive in stderr ed elimina il flusso dopo ogni record. |
Cloud Logging standard2 |
Supporto del plug-in DataNucleus 2.x | Supportato | Non supportato4 |
Note:
Se la tua app non utilizza i servizi in bundle legacy, i runtime Java di seconda generazione possono eseguire qualsiasi framework Java, a condizione che tu pacchettizzi un server web configurato per rispondere alle richieste HTTP sulla porta specificata dalla variabile di ambiente
PORT
(opzione consigliata) o sulla porta 8080. Ad esempio, i runtime Java di seconda generazione possono eseguire un JAR Spring Boot Uber JAR così com'è. Per altri esempi, consulta la sezione Flessibilità del framework.Se la tua app utilizza i servizi in bundle legacy, App Engine ne esegue il deployment utilizzando Jetty nello stesso modo del runtime Java 8.
Il logging nei runtime Java di seconda generazione segue lo standard di logging in Cloud Logging. Nei runtime Java di seconda generazione, i log delle app non sono più raggruppati con i log delle richieste, ma sono separati in record diversi. Per saperne di più su lettura e scrittura dei log nei runtime Java di seconda generazione, consulta la guida alla registrazione.
Per configurare un'app non threadsafe nel runtime Java di seconda generazione, in modo simile all'impostazione di
<threadsafe>false</threadsafe>
in Java 8, imposta il valore massimo di contemporaneità su 1 nel fileapp.yaml
o nel fileappengine-web.xml
se utilizzi i servizi in bundle legacy.Google non supporta la libreria DataNucleus nei runtime di seconda generazione. Le versioni più recenti di DataNucleus sono incompatibili con le versioni precedenti in Java 8. Per accedere a Datastore, ti consigliamo di utilizzare la libreria client in modalità Datastore o la soluzione Java Objectify (versione 6 o successiva). Objectify è un'API open source per Datastore che fornisce un livello di astrazione superiore.
Differenze di utilizzo della memoria
Per i runtime di seconda generazione, la base di utilizzo della memoria è maggiore rispetto ai runtime di prima generazione. Ciò è dovuto a più fattori, ad esempio diverse versioni delle immagini di base e alle differenze nel modo in cui le due generazioni calcolano l'utilizzo della memoria.
I runtime di seconda generazione calcolano l'utilizzo della memoria dell'istanza come somma di ciò che viene usato da un processo di applicazione e del numero di file dell'applicazione memorizzati nella cache in modo dinamico. Per evitare che le applicazioni che consumano molta memoria subiscano arresti delle istanze a causa del superamento dei limiti di memoria, esegui l'upgrade a una classe di istanza più grande con più memoria.
Differenze di utilizzo della CPU
I runtime di seconda generazione possono notare una base di utilizzo della CPU più elevata in caso di avvio a freddo delle istanze. A seconda della configurazione di scalabilità di un'applicazione, questo potrebbe avere effetti collaterali involontari, ad esempio un numero di istanze più elevato del previsto se un'applicazione è configurata per la scalabilità in base all'utilizzo della CPU. Per evitare questo problema, esamina e testa le configurazioni di scalabilità delle applicazioni per assicurarti che il numero di istanze sia accettabile.
Differenze nell'intestazione delle richieste
I runtime di prima generazione consentono di inoltrare all'applicazione le intestazioni delle richieste con trattini bassi (ad es. X-Test-Foo_bar
). I runtime
di seconda generazione introducono Nginx nell'architettura host. A seguito di questa modifica, i runtime di seconda generazione sono configurati in modo da rimuovere automaticamente le intestazioni con trattini bassi (_
). Per evitare problemi dell'applicazione, evita di utilizzare i trattini bassi nelle intestazioni delle richieste dell'applicazione.
Flessibilità del framework
I runtime Java di seconda generazione non includono framework di servizi web, a meno che non utilizzi i servizi in bundle legacy. Ciò significa che puoi utilizzare un framework diverso da un framework basato su servlet. Se utilizzi i servizi in bundle legacy, i runtime Java di seconda generazione forniscono il framework di pubblicazione web Jetty.
Esistono hello world
esempi che utilizzano i framework web Java più diffusi nel repository GitHub di Google Cloud:
Migrazione di XML nei formati di file YAML
gcloud CLI non supporta i seguenti formati file:
cron.xml
datastore-index.xml
dispatch.xml
queue.xml
I seguenti esempi mostrano come eseguire la migrazione dei file xml
in
file yaml
.
Migrazione automatica dei file
Per eseguire automaticamente la migrazione dei tuoi file xml
:
Devi avere gcloud CLI versione 226.0.0 o successiva. Per eseguire l'aggiornamento alla versione più recente:
gcloud components update
Per ogni file di cui vuoi eseguire la migrazione, specifica uno dei seguenti sottocomandi (
cron-xml-to-yaml
,datastore-indexes-xml-to-yaml
,dispatch-xml-to-yaml
,queue-xml-to-yaml
) e il nome del file:gcloud beta app migrate-config queue-xml-to-yaml MY-QUEUE-XML-FILE.xml
Ricontrolla manualmente il file convertito prima di eseguire il deployment in produzione.
Per una conversione di file da
xml
ayaml
di esempio riuscita, consulta le schede Migrazione manuale dei file.
Migrazione manuale dei file
Per eseguire manualmente la migrazione dei file xml
in yaml
file:
cron.yaml
Crea un file cron.yaml
con un oggetto cron
contenente un elenco di oggetti,
ciascuno con campi corrispondenti a ciascuno degli attributi del tag <cron>
nel
file cron.xml
, come mostrato di seguito.
File cron.yaml
convertito:
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'
File cron.xml
originale:
<?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>
Per ulteriori informazioni, consulta la documentazione di riferimento cron.yaml
.
dispatch.yaml
Crea un file dispatch.yaml
con un oggetto dispatch
contenente un elenco di oggetti, ciascuno con campi corrispondenti a ciascuno degli attributi del tag <dispatch>
nel file dispatch.xml
, come mostrato di seguito.
File dispatch.yaml
convertito:
dispatch:
- url: '*/favicon.ico'
module: default
- url: 'simple-sample.uc.r.appspot.com/'
module: default
- url: '*/mobile/*'
module: mobile-frontend
File dispatch.xml
originale
<?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>
Per ulteriori informazioni, consulta la documentazione di riferimento dispatch.yaml
index.yaml
Crea un file index.yaml
con un oggetto indexes
contenente un elenco di oggetti, ciascuno con campi corrispondenti a ciascuno degli attributi di tag <datastore-index>
nel file datastore-indexes.xml
, come mostrato di seguito.
File index.yaml
convertito:
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
File datastore-index.xml
originale:
<?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>
Per ulteriori informazioni, consulta la documentazione di riferimento index.yaml
.
queue.yaml
Crea un file queue.yaml
con un oggetto queue
contenente un elenco di oggetti, ciascuno con campi corrispondenti a ciascuno degli attributi del tag <queue>
nel file queue.xml
, come mostrato di seguito.
File queue.yaml
convertito:
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
File queue.xml
originale:
<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>