Halaman ini membahas petunjuk untuk bermigrasi dari runtime Java generasi pertama ke generasi kedua. Untuk mengupgrade aplikasi generasi kedua agar dapat menggunakan versi Java terbaru yang didukung, lihat Mengupgrade aplikasi yang ada.
Java 8 telah mencapai akhir dukungan pada 31 Januari 2024. Aplikasi Java 8 yang ada akan terus berjalan dan menerima traffic. Namun, App Engine mungkin memblokir deployment ulang aplikasi yang menggunakan runtime setelah tanggal akhir dukungannya. Sebaiknya Anda bermigrasi ke versi Java terbaru yang didukung dengan menggunakan panduan di halaman ini.
Dengan bermigrasi ke runtime Java generasi kedua, Anda dapat menggunakan fitur bahasa terbaru dan mem-build aplikasi yang lebih portabel dengan kode idiomatis.
Memahami opsi migrasi Anda
Untuk mengurangi upaya dan kompleksitas migrasi runtime, lingkungan standar App Engine memungkinkan Anda mengakses banyak layanan dan API paket lama, seperti Memcache, di runtime Java generasi kedua. Aplikasi Java Anda dapat memanggil API layanan paket melalui JAR API App Engine, dan mengakses sebagian besar kemampuan yang sama seperti pada runtime Java 8.
Anda juga memiliki opsi untuk menggunakan produk Google Cloud yang menawarkan fungsi serupa dengan layanan paket lama. Produk Google Cloud ini menyediakan Library Klien Cloud untuk Java yang idiomatis. Untuk paket layanan yang tidak tersedia sebagai produk terpisah di Google Cloud, seperti pemrosesan gambar, penelusuran, dan pesan, Anda dapat menggunakan penyedia pihak ketiga atau solusi lain yang disarankan.
Untuk mempelajari lebih lanjut cara bermigrasi ke layanan yang tidak dipaketkan, lihat Bermigrasi dari layanan paket.
Ada beberapa perbedaan dalam melakukan migrasi runtime, tergantung apakah Anda memilih untuk menggunakan layanan paket lama atau tidak:
Bermigrasi ke runtime Java generasi kedua dengan paket layanan | Bermigrasi ke runtime Java generasi kedua tanpa paket layanan |
---|---|
Akses layanan paket menggunakan JAR API App Engine. | Atau, gunakan produk Google Cloud atau layanan pihak ketiga yang direkomendasikan. |
Gunakan
Anda mungkin juga perlu mengonfigurasi file YAML tambahan, tergantung pada fitur yang digunakan aplikasi Anda. |
Gunakan
Anda mungkin juga perlu mengonfigurasi file YAML tambahan, tergantung pada fitur yang digunakan aplikasi Anda. |
Aplikasi di-deploy melalui Jetty. Menggunakan format WAR untuk mengemas aplikasi Anda. | Aplikasi di-deploy menggunakan server Anda sendiri. Gunakan format JAR untuk mengemas aplikasi Anda. Untuk mempelajari lebih lanjut cara mengonversi file WAR yang sudah ada menjadi JAR yang dapat dieksekusi, lihat Memaketkan ulang file WAR. |
Ringkasan proses migrasi
Berikut beberapa perubahan yang mungkin harus Anda buat pada aplikasi Java 8 App Engine yang ada dan proses deployment untuk menggunakan runtime Java generasi kedua:
- Download Google Cloud CLI.
- Lakukan migrasi dari plugin Maven App Engine mandiri ke plugin Maven berbasis gcloud CLI atau plugin Gradle berbasis gcloud CLI.
- Instal JAR API App Engine jika Anda menggunakan layanan paket lama.
Perbedaan utama antara Java 8 dan runtime Java generasi kedua
Berikut adalah ringkasan perbedaan antara runtime Java 8 dan runtime Java generasi kedua di lingkungan standar App Engine:
Runtime Java 8 | Runtime Java generasi kedua | |
---|---|---|
Deployment server | Server di-deploy untuk Anda menggunakan Jetty | Jika aplikasi Anda tidak menggunakan layanan paket lama, Anda harus men-deploy server sendiri.1 |
Layanan paket lama App Engine | Tersedia | Tersedia |
Kemampuan menggunakan Library Klien Cloud untuk Java | Ya | Ya |
Dukungan Ekstensi bahasa dan library sistem | Ya | Ya |
Akses jaringan eksternal | Ya | Ya |
Akses sistem file | Akses baca/tulis ke /tmp
|
Akses baca/tulis ke /tmp
|
Runtime bahasa | Diubah untuk App Engine | Runtime open source yang tidak dimodifikasi |
Mekanisme isolasi | Sandbox container berbasis gVisor | Sandbox container berbasis gVisor |
Menguji dengan server pengembangan lokal | Didukung | Didukung |
Konfigurasi keamanan thread | Dapat ditentukan dalam file appengine-web.xml .
|
Tidak dapat ditentukan dalam file konfigurasi. Semua aplikasi dianggap aman untuk thread.3 |
Logging | Menggunakan java.util.logging. ConsoleHandler , yang menulis ke stderr dan mengosongkan aliran data setelah setiap pencatatan data. |
Cloud Logging Standar 2 |
Dukungan plugin DataNucleus 2.x | Didukung | Tidak didukung 4 |
Catatan:
Jika aplikasi Anda tidak menggunakan layanan paket lama, runtime Java generasi kedua dapat menjalankan framework Java apa pun selama Anda mengemas server web yang dikonfigurasi untuk merespons permintaan HTTP pada port yang ditentukan oleh variabel lingkungan
PORT
(direkomendasikan) atau pada port 8080. Misalnya, runtime Java generasi kedua dapat menjalankan Spring Boot Uber JAR sebagaimana adanya. Untuk contoh lainnya, lihat bagian Fleksibilitas framework.Jika aplikasi Anda menggunakan layanan paket lama, App Engine akan men-deploy-nya menggunakan Jetty dengan cara yang sama seperti pada runtime Java 8.
Logging di runtime Java generasi kedua mengikuti standar logging di Cloud Logging. Pada runtime Java generasi kedua, log aplikasi tidak lagi dipaketkan dengan log permintaan, tetapi dipisahkan dalam data yang berbeda. Untuk mempelajari lebih lanjut cara membaca dan menulis log di runtime Java generasi kedua, lihat panduan logging.
Untuk mengonfigurasi aplikasi non-threadsafe di runtime Java generasi kedua, mirip dengan cara menetapkan
<threadsafe>false</threadsafe>
di Java 8, tetapkan konkurensi maksimum ke 1 di fileapp.yaml
atau fileappengine-web.xml
jika menggunakan layanan paket lama.Google tidak mendukung library DataNucleus di runtime generasi kedua. DataNucleus versi yang lebih baru tidak kompatibel dengan versi yang digunakan di Java 8. Untuk mengakses Datastore, sebaiknya gunakan solusi library klien mode Datastore atau Objectify Java (versi 6 atau yang lebih baru). Objectify adalah API open source untuk Datastore yang memberikan tingkat abstraksi lebih tinggi.
Perbedaan penggunaan memori
Runtime generasi kedua memiliki dasar penggunaan memori yang lebih tinggi dibandingkan dengan runtime generasi pertama. Hal ini disebabkan oleh beberapa faktor, seperti versi gambar dasar yang berbeda, dan perbedaan dalam cara kedua generasi menghitung penggunaan memori.
Runtime generasi kedua menghitung penggunaan memori instance sebagai jumlah dari yang digunakan proses aplikasi, dan jumlah file aplikasi yang di-cache secara dinamis di memori. Agar aplikasi yang intensif memori tidak mengalami penghentian instance karena melebihi batas memori, upgrade ke class instance yang lebih besar dengan lebih banyak memori.
Perbedaan penggunaan CPU
Runtime generasi kedua dapat melihat baseline penggunaan CPU yang lebih tinggi setelah cold start instance. Bergantung pada konfigurasi penskalaan aplikasi, hal ini mungkin memiliki efek samping yang tidak diinginkan, seperti jumlah instance yang lebih tinggi dari yang diperkirakan jika aplikasi dikonfigurasi untuk diskalakan berdasarkan penggunaan CPU. Untuk menghindari masalah ini, tinjau dan uji konfigurasi penskalaan aplikasi untuk memastikan jumlah instance dapat diterima.
Perbedaan header permintaan
Runtime generasi pertama memungkinkan header permintaan dengan garis bawah
(misalnya, X-Test-Foo_bar
) diteruskan ke aplikasi. Runtime generasi kedua memperkenalkan Nginx ke dalam arsitektur host. Sebagai akibat dari perubahan
ini, runtime generasi kedua dikonfigurasi untuk otomatis menghapus
header dengan garis bawah (_
). Untuk mencegah masalah aplikasi, hindari penggunaan
garis bawah di header permintaan aplikasi.
Fleksibilitas framework
Runtime Java generasi kedua tidak menyertakan framework penayangan web apa pun kecuali jika Anda menggunakan layanan paket lama. Artinya, Anda dapat menggunakan framework selain framework berbasis servlet. Jika Anda menggunakan layanan paket lama, runtime Java generasi kedua akan menyediakan framework penayangan web Jetty.
Ada hello world
contoh yang menggunakan framework web Java populer di
repositori GitHub Google Cloud:
Memigrasikan format file XML ke YAML
gcloud CLI tidak mendukung format file berikut:
cron.xml
datastore-index.xml
dispatch.xml
queue.xml
Contoh berikut menunjukkan cara memigrasikan file xml
ke
file yaml
.
Memigrasikan file secara otomatis
Untuk memigrasikan file xml
secara otomatis:
Anda harus memiliki gcloud CLI versi 226.0.0 atau yang lebih baru. Untuk mengupdate ke versi terbaru:
gcloud components update
Untuk setiap file yang ingin dimigrasikan, tentukan salah satu subperintah berikut (
cron-xml-to-yaml
,datastore-indexes-xml-to-yaml
,dispatch-xml-to-yaml
,queue-xml-to-yaml
) dan nama file:gcloud beta app migrate-config queue-xml-to-yaml MY-QUEUE-XML-FILE.xml
Periksa kembali file yang dikonversi secara manual sebelum men-deploy ke produksi.
Untuk mengetahui contoh konversi file
xml
keyaml
yang berhasil, lihat tab Memigrasikan file secara manual.
Memigrasikan file secara manual
Untuk memigrasikan file xml
secara manual ke file yaml
:
cron.yaml
Buat file cron.yaml
dengan objek cron
yang berisi daftar objek,
masing-masing dengan kolom yang sesuai dengan setiap atribut tag <cron>
dalam
file cron.xml
, sebagai yang ditunjukkan di bawah ini.
File cron.yaml
yang dikonversi:
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
asli:
<?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>
Untuk informasi selengkapnya, lihat dokumentasi referensi cron.yaml
.
dispatch.yaml
Buat file dispatch.yaml
dengan objek dispatch
yang berisi daftar
objek, masing-masing dengan kolom yang sesuai dengan setiap atribut tag <dispatch>
dalam file dispatch.xml
, sebagai yang ditunjukkan di bawah ini.
File dispatch.yaml
yang dikonversi:
dispatch:
- url: '*/favicon.ico'
module: default
- url: 'simple-sample.uc.r.appspot.com/'
module: default
- url: '*/mobile/*'
module: mobile-frontend
File dispatch.xml
asli
<?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>
Untuk informasi selengkapnya, lihat dokumentasi referensi dispatch.yaml
index.yaml
Buat file index.yaml
dengan objek indexes
yang berisi daftar
objek, masing-masing dengan kolom yang sesuai dengan setiap atribut tag <datastore-index>
dalam file datastore-indexes.xml
, sebagai yang ditunjukkan di bawah ini.
File index.yaml
yang dikonversi:
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
asli:
<?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>
Untuk informasi selengkapnya, lihat dokumentasi referensi index.yaml
.
queue.yaml
Buat file queue.yaml
dengan objek queue
yang berisi daftar
objek, masing-masing dengan kolom yang sesuai dengan setiap atribut tag <queue>
dalam file queue.xml
, sebagai yang ditunjukkan di bawah ini.
File queue.yaml
yang dikonversi:
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
asli:
<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>