


Java Juga Boleh Tanpa Pelayan: Menggunakan GraalVM untuk Permulaan Dingin Pantas
Jan 07, 2025 am 06:16 AMpengenalan
Pendekatan yang agak biasa apabila ia datang untuk bekerja dengan kod tanpa pelayan ialah menulisnya sebagai aplikasi Python, Node atau Go memandangkan reputasi mereka untuk permulaan sejuk yang sangat cepat.
Tetapi bagaimana jika kita berhadapan dengan apl Java sedia ada yang menyasarkan persekitaran tanpa pelayan seperti AWS Lambda? Mungkin sebahagian besar pangkalan kod kami menjadi tuan rumah Java dan kami telah membangunkan ekosistem alat dan perpustakaan yang kaya yang kami ingin gunakan semula. Menulis semula keseluruhan kumpulan aplikasi sedemikian ke dalam bahasa yang berbeza adalah mahal, apatah lagi, kami menyerahkan ciri seperti keselamatan jenis statik dan pengoptimuman masa penyusunan.
Suatu ketika dahulu, saya berdepan dengan senario tepat ini: 9 apl AWS Lambda yang ditulis dalam Java yang akan menjadi sangat perlahan pada permulaan sejuk sehingga beberapa daripadanya kadang-kadang tamat masa.
Lambdas yang dimaksudkan diletakkan di belakang Gerbang API dan digunakan untuk tugas pentadbir dengan memanggil API REST yang sepadan. Kefungsian ini tidak begitu banyak digunakan dan oleh itu mengalami permulaan yang sejuk tidak dapat dielakkan; walau bagaimanapun, kerana ini bukan perkhidmatan kritikal, ia merupakan peluang yang sesuai untuk percubaan: untuk mengetahui sama ada Lambda ini boleh diselamatkan.
Tidak lama kemudian saya terserempak dengan beberapa catatan blog lain tentang pembangun yang berjaya menggunakan GraalVM dan rangka kerja seperti Quarkus untuk menangani masalah ini. Jadi saya telah memutuskan untuk mencubanya sendiri.
Tetapi apakah alatan ini?
GraalVM
Ringkasnya, GraalVM ialah Mesin Maya Java yang disertakan dengan set alat yang mampu menyusun Java kepada Imej Asli dan melaksanakannya menggunakan Graal JVM.
Biasanya Java menggunakan pengkompil "Just In Time" (JIT), yang seperti namanya, melaksanakan pengoptimuman dan penyusunan semasa pelaksanaan kod kami. Aplikasi yang berjalan lama mendapat manfaat daripada ini memandangkan pengoptimum JVM sentiasa memantau pelaksanaan program dan melakukan penalaan halus yang lebih masa diterjemahkan kepada prestasi yang lebih baik.
Ini bagus jika aplikasi dibuat seketika, dan dijangka berjalan selama beberapa jam atau lebih, tetapi tidak begitu hebat jika kita berurusan dengan Kubernetes, AWS Lambdas dan kerja kelompok yang berharap untuk boot apl Java dengan cepat, berprestasi operasi dan skala sensitif masa bergantung pada permintaan - bercakap tentang lag turbo untuk peminat kereta di luar sana.
Dan di sinilah keupayaan Imej Asli GraalVM melangkah masuk untuk membantu. Daripada menggunakan pengkompil JIT, ia memilih pendekatan yang sangat berbeza untuk menyusun kod kami lebih awal daripada masa (AOT). Ia pra-membakar pai kami menggunakan analisis kod statik dan juga pra-memulakan kelas tertentu semasa masa binaan supaya ia bersedia untuk menyala pada bila-bila masa kod aplikasi kami dilaksanakan.
Hasilnya? Permulaan sejuk yang sangat pantas, yang menjadikan Imej Asli sangat berkebolehan dalam domain tanpa pelayan yang apl berumur pendek dan perlu but dengan cepat.
Satu perkara yang perlu diambil perhatian ialah walaupun GraalVM berkemampuan AOT, ia juga boleh berfungsi sebagai pengganti drop-in untuk JVM sedia ada yang menawarkan prestasi yang lebih baik memandangkan pengkompil JIT baharu GraalVM yang ditulis dalam Java.
Tetapi tunggu, ada lagi! Oleh kerana Imej Asli termasuk hanya kod yang berada pada laluan pelaksanaan yang diketahui, kami memangkas lemak dan semua kelas Java yang belum diisytiharkan secara eksplisit untuk disimpan tidak akan tersedia. Oleh kerana kami hanya menyimpan bit yang dijangka akan dilaksanakan, kami meningkatkan keselamatan aplikasi kami.
Ambil contoh kelemahan Log4J yang terkenal yang menggunakan Pelaksanaan Kod Jauh sebagai cara untuk menjejaskan hos. Dengan Imej Asli, rantaian alat sangat tidak mungkin berjaya kerana kepingan kod perpustakaan yang diperlukan untuk menyampaikan serangan itu tidak dapat dicapai.
Quarkus
Quarkus sebaliknya, ialah rangka kerja Java yang dioptimumkan untuk aplikasi tanpa pelayan yang disertakan dengan kotak alat yang memudahkan pembinaan Imej Asli dengan menawarkan sambungan untuk mengkonfigurasi dan membina AWS Lambdas secara khusus sebagai boleh laku asli.
Penyusun C1
Semasa perjalanan pengoptimuman Lambda saya, saya juga telah menemui teknik pengoptimuman alternatif. Salah satu daripada pengoptimuman tersebut ialah penggunaan eksklusif pengkompil C1 yang dicadangkan semasa pelaksanaan Lambda yang telah berjanji untuk menyampaikan permulaan sejuk yang lebih cepat. Biasanya, aplikasi Java yang dijalankan di dalam JVM menggunakan kompilasi berperingkat yang terdiri daripada C1 yang lebih pantas, tetapi kurang optimum, diikuti oleh C2 yang lebih perlahan, tetapi menawarkan prestasi yang lebih optimum untuk apl Java yang dilaksanakan untuk masa yang lama. Memandangkan Lambdas berumur pendek, faedah kompilasi C2 boleh diabaikan.
Panduan berjalan melalui proses mengkonfigurasi kompilasi C1 untuk AWS Lambdas tersedia di sini.
Sudah tentu saya ingin tahu berapa banyak peningkatan yang boleh ditawarkan oleh teknik ini berbanding dengan pelan induk GraalVM saya yang sedia ada, jadi saya juga telah memasukkannya ke dalam penemuan saya di bawah.
Butiran lanjut tentang kompilasi berperingkat JVM serta pengkompil JIT serba baharu GraalVM boleh didapati dalam artikel Baeldung ini.
"Tetapi tunggu, bagaimana dengan AWS SnapStart?"
Ironisnya, beberapa bulan selepas saya menghantar perubahan saya kepada pengeluaran, AWS menghasilkan keupayaan SnapStart terbaharu mereka, yang mengambil gambar Lambda yang sedang berjalan dan bukannya memulakannya semula sekali lagi, ia menggunakan imej syot kilat sebagai titik pemulihan menjanjikan permulaan sejuk yang lebih cepat. Saya terpaksa mencubanya untuk mengetahui sama ada penggunaan GraalVM adalah satu usaha yang sia-sia dan juga memasukkannya dalam penemuan saya.
Perlu diingat bahawa untuk memanfaatkan SnapStart sepenuhnya, pemfaktor semula kod diperlukan untuk menggunakan cangkuk beforeCheckpoint dan afterRestore (butiran lanjut di sini). Memandangkan saya ingin mengelakkan sebarang perubahan kod utama jika boleh, saya telah menggunakan ciri ini "seadanya", tanpa melaksanakan kaedah ini dan menyusun semula sebarang kod.
Pelan Induk
Kini kembali ke GraalVM! Saya terkejut, selepas memasukkan penyelesaian ini, tiada perubahan kod Java sama sekali diperlukan selain daripada menambah dan melaraskan fail konfigurasi binaan dan beberapa metadata yang diperlukan.
Bunyi terlalu bagus untuk menjadi kenyataan?
Mungkin sedikit. Memandangkan kami menggunakan kompilasi AOT, dalam dunia Java, ini menimbulkan cabaran tertentu jika melibatkan penggunaan ciri bahasa seperti Reflections, Proxies, Interfaces dan Service registry yang banyak bergantung kepada perpustakaan. Inilah sebabnya mengapa pengkompil GraalVM memerlukan metadata konfigurasi tambahan untuk diisytiharkan yang secara eksplisit mendaftarkan kelas dan perkhidmatan tertentu supaya mereka boleh dimasukkan ke dalam artifak akhir. GraalVM menyediakan apa yang dipanggil ejen yang boleh digunakan untuk berjalan bersama boleh laku anda untuk mengenal pasti secara automatik konfigurasi yang diperlukan yang boleh menjadikan proses ini lebih mudah.
Quarkus menyediakan beberapa sambungan untuk perpustakaan terkenal untuk menjadikannya "mesra imej asli", tetapi memandangkan saya bekerja dengan pangkalan kod sedia ada, dan matlamat saya adalah untuk mengelakkan sebarang refactor utama (atau sebarang perubahan kod dalam perkara itu ), saya memutuskan untuk mencipta fail konfigurasi yang diperlukan yang diperlukan oleh perpustakaan sedia ada untuk menghasilkan Imej Asli dengan jayanya.
Berhati-hati bahawa penyusunan Imej Asli adalah intensif sumber dan ia mengambil masa yang jauh lebih lama berbanding kompilasi kod bait yang menyasarkan masa jalan JVM standard. Kemungkinannya ialah anda mungkin mendapati diri anda terpaksa memperuntukkan lebih banyak RAM kepada nod binaan untuk mengelakkan masalah ingatan, yang tidak sepatutnya menjadi pemecah perjanjian, tetapi pastinya sesuatu yang perlu diingat.
Sekarang saya telah mengumpulkan Lambdas Imej Asli saya dan dibungkus, tiba masanya untuk menggunakan ia ke dalam persekitaran ujian. Biasanya, Java Lambdas menggunakan Java Runtimes AWS untuk dilaksanakan; walau bagaimanapun, memandangkan kami cuba menggunakan Imej Asli yang merupakan artifak binari yang mengandungi kod apl kami yang dibalut di dalam Graal JVM, kami mesti memilih salah satu daripada persekitaran Amazon Linux "Tersuai" yang ditawarkan oleh AWS.
Metodologi Pengujian
Saya telah menggunakan Koleksi API Posmen untuk menghantar permintaan kepada semua 9 Lambda dan mengukur masa tindak balas mula sejuk untuk setiap teknik yang dinyatakan di atas. Untuk memastikan saya sentiasa mengalami permulaan yang sejuk, saya telah memuatkan semula konfigurasi Lambda sasaran yang memastikan bahawa seruan seterusnya tidak akan menggunakan contoh yang mungkin sudah hangat. Semua Lambdas telah dikonfigurasikan dengan 1GB RAM. Saya juga telah mengukur satu doa untuk setiap konfigurasi memandangkan proses itu memakan masa; namun, masa tindak balas yang diperhatikan memberikan gambaran yang cukup jelas.
Keputusan
Jadi adakah ia berjaya? Sudah tentu! Berikut adalah keputusannya:
Dan pemenang yang jelas ialah: GraalVM Native Images - secara purata, ia telah menghasilkan kelajuan 3x ganda berbanding dengan Java Lambdas yang tidak berubah - tiada lagi masa tamat, dan masa tindak balas yang lebih baik, itulah yang saya mahukan capai.
SnapStart tidak berprestasi sebaik yang saya fikirkan tanpa sebarang perubahan kod. Apabila pengkompil C1 digunakan sebagai tambahan kepada ciri SnapStart, ia mengurangkan masa mula sejuk lebih jauh, tetapi masih tidak mengalahkan Imej Asli GraalVM. Itu bukan untuk mengatakan bahawa ia bukan pilihan yang berdaya maju sebagai penambahbaikan yang cepat dan mudah untuk dilaksanakan; walau bagaimanapun, jika kami ingin mengoptimumkan Lambda kami sebanyak mungkin dan kami mempunyai sedikit masa dan sumber untuk melaraskan konfigurasi dan proses binaan kami, GraalVM pastinya lebih unggul dalam hal prestasi dan keselamatan.
Jejak Memori
Seperti yang didakwa oleh GraalVM, Native Images memerlukan kurang sumber untuk dijalankan dengan berkesan berbanding rakan JVM biasa mereka. Saya ingin melihat bagaimana prestasi permulaan sejuk dan permulaan hangat akan bertahan jika saya ingin mengurangkan jumlah RAM yang perlu digunakan oleh Lambdas ini. Kali ini saya telah memilih hanya satu apl Lambda untuk melakukan ujian ini. Berikut adalah keputusannya:
Dan pada janji mereka mereka telah menunaikan! JVM Lambdas biasa kehabisan memori apabila mencuba konfigurasi 256 MB dan lebih rendah, manakala Imej Asli kelihatan tidak berfasa dan terus dilaksanakan. Jika bukan kerana 128 MB sebagai pilihan memori yang tersedia paling rendah, saya tertanya-tanya berapa banyak yang boleh kita lakukan. Imej Asli bukan sahaja lebih pantas pada permulaan sejuk, tetapi menawarkan prestasi yang konsisten apabila bekerja dengan sumber terhad, yang diterjemahkan kepada kos operasi yang lebih rendah.
Kesimpulan
Ekosistem Java kaya dan luas dengan banyak teknologi baharu dan peningkatan yang muncul setiap hari yang mengekalkan Java dalam permainan apabila ia berkaitan dengan aplikasi tanpa pelayan. Salah satu teknologi baru muncul ialah GraalVM. Apa yang bermula sebagai projek penyelidikan kini perlahan-lahan diterima pakai dan menjadi alternatif yang berdaya maju kepada JVM standard seperti HotSpot. Dalam catatan blog ini, saya hampir tidak menconteng apa yang GraalVM tawarkan dan saya akan menggalakkan pembaca untuk menerokainya dengan lebih lanjut. Terdapat beberapa kisah kejayaan daripada syarikat seperti Adyen (pautan artikel) atau Facebook (pautan artikel) yang dapat menggunakan GraalVM untuk menjimatkan masa dan wang.
Jadi pada kali seterusnya anda akan memberikan diskaun kepada Java sebagai pilihan, cuba GraalVM. Dan kini Spring Boot 3 menyokong Imej Asli GraalVM di luar kotak, lebih mudah berbanding sebelum ini untuk menggunakannya untuk beban kerja tanpa pelayan anda untuk memanfaatkan prestasi, penggunaan sumber yang rendah dan keselamatan tambahan yang ditawarkan oleh GraalVM.
Atas ialah kandungan terperinci Java Juga Boleh Tanpa Pelayan: Menggunakan GraalVM untuk Permulaan Dingin Pantas. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undress AI Tool
Gambar buka pakaian secara percuma

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Perbezaan antara hashmap dan hashtable terutamanya dicerminkan dalam keselamatan benang, sokongan nilai null dan prestasi. 1. Dari segi keselamatan benang, hashtable adalah benang selamat, dan kaedahnya kebanyakannya kaedah segerak, sementara hashmap tidak melakukan pemprosesan penyegerakan, yang bukan benang-selamat; 2. Dari segi sokongan nilai null, hashmap membolehkan satu kunci null dan nilai null berbilang, manakala hashtable tidak membenarkan kekunci atau nilai null, jika tidak, nullPointerException akan dibuang; 3. Dari segi prestasi, hashmap lebih cekap kerana tidak ada mekanisme penyegerakan, dan Hashtable mempunyai prestasi penguncian yang rendah untuk setiap operasi. Adalah disyorkan untuk menggunakan ConcurrentHashMap sebaliknya.

Java menggunakan kelas pembalut kerana jenis data asas tidak dapat mengambil bahagian secara langsung dalam operasi berorientasikan objek, dan bentuk objek sering diperlukan dalam keperluan sebenar; 1. Kelas koleksi hanya boleh menyimpan objek, seperti senarai menggunakan tinju automatik untuk menyimpan nilai berangka; 2. Generik tidak menyokong jenis asas, dan kelas pembungkusan mesti digunakan sebagai parameter jenis; 3. Kelas pembungkusan boleh mewakili nilai null untuk membezakan data yang tidak tersendiri atau hilang; 4. Kelas pembungkusan menyediakan kaedah praktikal seperti penukaran rentetan untuk memudahkan parsing dan pemprosesan data, jadi dalam senario di mana ciri -ciri ini diperlukan, kelas pembungkusan sangat diperlukan.

Penyusun JIT mengoptimumkan kod melalui empat kaedah: kaedah dalam talian, pengesanan tempat panas dan penyusunan, spekulasi jenis dan devirtualisasi, dan penghapusan operasi yang berlebihan. 1. Kaedah sebaris mengurangkan panggilan overhead dan memasukkan kaedah kecil yang sering dipanggil terus ke dalam panggilan; 2. Pengesanan tempat panas dan pelaksanaan kod frekuensi tinggi dan mengoptimumkannya untuk menjimatkan sumber; 3. Jenis spekulasi mengumpul maklumat jenis runtime untuk mencapai panggilan devirtualisasi, meningkatkan kecekapan; 4. Operasi berlebihan menghapuskan pengiraan dan pemeriksaan yang tidak berguna berdasarkan penghapusan data operasi, meningkatkan prestasi.

Staticmethodsininterfaceswereintroducedinjava8toallowutilityfunctionswithintheintheinterfaceitself.beforjava8, SuchfunctionsRequiredseparateHelpereHelperes, LeadingTodisorgaganizedCode.Now, staticmethodethreeKeybeeMeKeBeReSes, staticmethodeDethreeKeybeeMeKeBeReSes, staticmethodethreeKeybeeMeKeKeBeReSes, staticmethodeDethreeKeybeeMeKeKeBeReKeNey

Blok permulaan contoh digunakan dalam Java untuk menjalankan logik inisialisasi apabila membuat objek, yang dilaksanakan sebelum pembina. Ia sesuai untuk senario di mana beberapa pembina berkongsi kod inisialisasi, permulaan medan kompleks, atau senario permulaan kelas tanpa nama. Tidak seperti blok inisialisasi statik, ia dilaksanakan setiap kali ia ditegaskan, manakala blok permulaan statik hanya dijalankan sekali apabila kelas dimuatkan.

Injava, thefinalkeywordpreventsavariable'svaluefrombeingchangedafterassignment, butitsbehaviordiffersforprimitivesandobjectreferences.forprimitiveVariables, finalmakesthevalueconstant, asinfinalintmax_speed = 100;

Mod kilang digunakan untuk merangkum logik penciptaan objek, menjadikan kod lebih fleksibel, mudah dikekalkan, dan ditambah longgar. Jawapan teras adalah: dengan mengurus logik penciptaan objek secara berpusat, menyembunyikan butiran pelaksanaan, dan menyokong penciptaan pelbagai objek yang berkaitan. Keterangan khusus adalah seperti berikut: Mod Kilang menyerahkan penciptaan objek ke kelas kilang khas atau kaedah untuk diproses, mengelakkan penggunaan Newclass () secara langsung; Ia sesuai untuk senario di mana pelbagai jenis objek yang berkaitan dicipta, logik penciptaan boleh berubah, dan butiran pelaksanaan perlu disembunyikan; Sebagai contoh, dalam pemproses pembayaran, jalur, paypal dan contoh lain dicipta melalui kilang -kilang; Pelaksanaannya termasuk objek yang dikembalikan oleh kelas kilang berdasarkan parameter input, dan semua objek menyedari antara muka yang sama; Varian biasa termasuk kilang -kilang mudah, kaedah kilang dan kilang abstrak, yang sesuai untuk kerumitan yang berbeza.

Terdapat dua jenis penukaran: tersirat dan eksplisit. 1. Penukaran tersirat berlaku secara automatik, seperti menukar int untuk berganda; 2. Penukaran eksplisit memerlukan operasi manual, seperti menggunakan (int) mydouble. Kes di mana penukaran jenis diperlukan termasuk memproses input pengguna, operasi matematik, atau lulus pelbagai jenis nilai antara fungsi. Isu-isu yang perlu diperhatikan adalah: Mengubah nombor terapung ke dalam bilangan bulat akan memotong bahagian pecahan, mengubah jenis besar menjadi jenis kecil boleh menyebabkan kehilangan data, dan beberapa bahasa tidak membenarkan penukaran langsung jenis tertentu. Pemahaman yang betul tentang peraturan penukaran bahasa membantu mengelakkan kesilapan.
