Questa pagina illustra le istruzioni per la migrazione dai runtime Java di prima generazione a quelli di seconda generazione. Per eseguire l'upgrade dell'app di seconda generazione in modo che utilizzi l'app più recente supportata di Java, consulta l'articolo Eseguire l'upgrade di un'applicazione esistente.
Il 31 gennaio 2024 è terminato il supporto di Java 8. Le applicazioni Java 8 esistenti continueranno per eseguire e ricevere traffico. Tuttavia, App Engine potrebbe bloccare il rideployment delle applicazioni che utilizzano i runtime dopo la data di fine del supporto. Ti consigliamo di eseguire la migrazione alla versione più recente di Java supportata utilizzando le linee guida riportate in questa pagina.
Migrazione alla versione Java di seconda generazione runtime, consentono di usare funzionalità linguistiche aggiornate e di creare app portabile, con codice idiomatico.
Informazioni sulle opzioni di migrazione
Per ridurre le attività e la complessità della migrazione del runtime, l'ambiente standard di App Engine ti consente accedere a molti dei servizi e delle API in bundle legacy, come Memcache, nella seconda generazione runtime Java. 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 i prodotti Google Cloud che offrono con funzionalità simili a quelle dei precedenti servizi in bundle. Questi prodotti Google Cloud forniscono librerie client di Cloud per Java idiomatiche. Per i servizi in bundle che non sono disponibili come prodotti separati in Google Cloud, come l'elaborazione di immagini, la ricerca e la messaggistica, puoi utilizzare fornitori di terze parti o altre soluzioni alternative.
Per scoprire di più sulla migrazione ai servizi slegati, consulta Eseguire la migrazione dai servizi in bundle.
Esistono alcune differenze nella modalità di esecuzione della migrazione del runtime, a seconda se scegli di utilizzare i servizi in bundle legacy:
Migrazione ai runtime Java di seconda generazione con servizi in bundle | Migrazione a runtime Java di seconda generazione senza servizi in bundle |
---|---|
Accedi ai servizi integrati utilizzando il file JAR delle API di App Engine. | Se vuoi, utilizza servizi di terze parti o prodotti Google Cloud consigliati. |
Utilizza
Potresti anche dover configurare file YAML aggiuntivi, a seconda delle funzionalità utilizzate dalla tua app. |
Usa
Potresti anche dover configurare file YAML aggiuntivi a seconda delle funzionalità utilizzate dalla tua app. |
Il deployment delle app viene eseguito tramite Jetty. Utilizza il formato WAR per pacchettizzare la tua app. | Le app vengono implementate utilizzando il tuo server. Utilizza il formato JAR per pacchettizzare dell'app. Per scoprire di più sulla conversione del file WAR esistente in un JAR eseguibile, vedi Ripacchettizzazione di un file WAR. |
Panoramica del processo di migrazione
Di seguito sono elencate alcune modifiche che potresti dover apportare all'app App Engine Java 8 esistente e alla procedura di implementazione per utilizzare i runtime Java di seconda generazione:
- Scarica Google Cloud CLI.
- Esegui la migrazione dal plug-in Maven App Engine autonomo al plug-in Maven basato su gcloud CLI o al plug-in Gradle basato su gcloud CLI.
- Installa il file JAR dell'API App Engine se utilizzi i servizi integrati legacy.
Differenze principali tra i runtime Java 8 e di seconda generazione
Di seguito è riportato un riepilogo delle differenze tra Java 8 e i runtime Java di seconda generazione nell'ambiente standard di App Engine:
Runtime Java 8 | Runtime Java di seconda generazione | |
---|---|---|
Deployment del server | Server di cui è stato eseguito il deployment utilizzando Jetty | Se la tua app non utilizza i servizi in bundle legacy, devi eseguire il deployment personalmente un server.1 |
Servizi integrati legacy di App Engine | Fornito da Google | Fornito da Google |
Possibilità di utilizzare le librerie client di Cloud per Java | Sì | Sì |
Supporto delle estensioni di lingua e della libreria 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 della lingua | Modificato per App Engine | Ambiente di runtime open source non modificato |
Meccanismo di isolamento | Sandbox del container basato su gVisor | Sandbox dei container basata su gVisor |
Test con il server di sviluppo locale | Supportato | Supportato |
Configurazione di sicurezza dei thread | Può essere specificato nel file appengine-web.xml .
|
Non può essere specificato nei file di configurazione. Si presume che tutte le app siano sicure per i thread.3 |
Logging | Utilizza un java.util.logging. ConsoleHandler , che scrive in stderr e svuota lo stream dopo ogni record. |
Cloud Logging standard2 |
Supporto del plug-in DataNucleus 2.x | Supportato | Non supportato 4 |
Note:
Se la tua app non utilizza i servizi in bundle legacy, il cluster I runtime Java possono eseguire qualsiasi framework Java, purché pacchettizzi configurato per rispondere alle richieste HTTP sul porta specificata dalla variabile di ambiente
PORT
(consigliata) oppure on la porta 8080. Ad esempio, i runtime Java di seconda generazione possono eseguire un JAR Uber Spring Boot 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 come nel runtime di 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ù in bundle con i log delle richieste, ma sono separati in record diversi. Per apprendere per saperne di più sulla lettura e sulla scrittura dei log nei runtime Java di seconda generazione, consulta il guida al logging.
Per configurare un'app non sicura per thread nella runtime Java di seconda generazione, in modo simile all'impostazione
<threadsafe>false</threadsafe>
in Java 8, imposta la contemporaneità massima su 1 nelleapp.yaml
oppure Fileappengine-web.xml
se utilizzi i servizi legacy in bundle.Google non supporta la libreria DataNucleus nei runtime di seconda generazione. Le versioni più recenti di DataNucleus non sono compatibili con le versioni precedenti utilizzate 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 successive). Objectify è un'API open source per Datastore che fornisce un livello di astrazione superiore.
Differenze di utilizzo della memoria
I runtime di seconda generazione hanno una base di riferimento dell'utilizzo della memoria più elevata rispetto ai runtime di prima generazione. Ciò è dovuto a più fattori, come diversi versioni delle immagini di base e le differenze nel modo in cui le due generazioni calcolano la memoria all'utilizzo delle risorse.
I runtime di seconda generazione calcolano l'utilizzo della memoria dell'istanza come la somma di ciò che viene utilizzato da un processo dell'applicazione e del numero di file dell'applicazione memorizzati nella cache dinamicamente in memoria. Per evitare che le applicazioni che usano molta memoria utilizzino l'istanza arresti anomali dovuti al superamento dei limiti di memoria, esegui l'upgrade a una versione classe dell'istanza con più memoria.
Differenze nell'utilizzo della CPU
I runtime di seconda generazione possono vedere una base di utilizzo più alta della CPU al momento dell'istanza avvio a freddo. A seconda della configurazione di scalabilità di un'applicazione, effetti collaterali imprevisti, come un conteggio delle istanze più elevato del previsto è configurata per la scalabilità in base all'utilizzo della CPU. Per evitare questo problema, esamina e testa le configurazioni di scalabilità dell'applicazione per assicurarti che il numero di istanze sia accettabile.
Differenze nelle intestazioni delle richieste
I runtime di prima generazione consentono di inoltrare all'applicazione le intestazioni di richiesta con trattini bassi
(ad es. X-Test-Foo_bar
). I runtime di seconda generazione introducono Nginx nell'architettura host. Per effetto di ciò,
modifica, i runtime di seconda generazione sono configurati per rimuovere automaticamente
intestazioni con trattini bassi (_
). Per evitare problemi con l'applicazione, evita di utilizzare
trattini bassi nelle intestazioni delle richieste dell'applicazione.
Flessibilità del framework
I runtime Java di seconda generazione non includere framework per la pubblicazione sul web, a meno che tu non stia utilizzando 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 fornire il framework per la pubblicazione sul web di Jetty.
Nel repository GitHub di Google Cloud sono disponibili hello world
esempi che utilizzano framework web Java popolari:
Migrazione dei formati di file XML in 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
yaml
file.
Eseguire la migrazione dei file automaticamente
Per eseguire la migrazione automatica dei file xml
:
Devi disporre di gcloud CLI versione 226.0.0 o successive. 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
Controlla manualmente il file convertito prima di eseguire il deployment in produzione.
Per una conversione di file di esempio
xml
inyaml
riuscita, consulta le schede Eseguire la migrazione dei file manualmente.
Migrazione manuale dei file
Per eseguire manualmente la migrazione dei file xml
in file yaml
:
cron.yaml
Crea un file cron.yaml
con un oggetto cron
contenente un elenco di oggetti,
ciascuno con campi che corrispondono a ciascuno degli attributi del tag <cron>
in
il tuo 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 di cron.yaml
documentazione.
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 saperne di più, consulta la documentazione di riferimento di dispatch.yaml
.
index.yaml
Crea un file index.yaml
con un oggetto indexes
contenente un elenco di
ciascuno con campi che corrispondono a uno degli elementi <datastore-index>
nel tuo 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 di index.yaml
documentazione.
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>