In der dynamischen Landschaft der modernen Softwareentwicklung sind Microservices zum bevorzugten Architekturansatz geworden. Obwohl diese Methode zahlreiche Vorteile bietet, ist sie nicht ohne Herausforderungen. Probleme wie großer Speicherbedarf, längere Startzeiten und hohe CPU-Auslastung gehen häufig mit herkömmlichen JVM-basierten Diensten einher. Diese Herausforderungen wirken sich nicht nur auf die technischen Aspekte aus, sondern haben auch finanzielle Auswirkungen, die sich erheblich auf die Gesamtkosten für den Betrieb und die Wartung von Softwarelösungen auswirken können.
GraalVM Native Image ist eine Schlüsselfunktion von GraalVM, einer Hochleistungslaufzeit, die Unterstützung für verschiedene Programmiersprachen und Ausführungsmodi bietet. Insbesondere können Sie mit GraalVM Native Image Java-Anwendungen im Voraus in eigenständige native ausführbare Dateien kompilieren, ohne dass zur Laufzeit eine Java Virtual Machine (JVM) erforderlich ist. Dieser innovative Ansatz führt zu ausführbaren Dateien, die im Vergleich zu ihren herkömmlichen JVM-Gegenstücken nahezu sofortige Startzeiten und einen deutlich geringeren Speicherverbrauch aufweisen. Diese nativen ausführbaren Dateien werden sorgfältig erstellt und enthalten nur die wesentlichen Klassen, Methoden und abhängigen Bibliotheken, die für die Funktionalität der Anwendung unerlässlich sind. Über seine technischen Fähigkeiten hinaus erweist sich GraalVM Native Image als strategische Lösung mit weitreichenden Auswirkungen. Es meistert nicht nur technische Herausforderungen, sondern bietet auch überzeugende finanzielle Argumente. Durch die Erleichterung der Entwicklung effizienter, sicherer und sofort skalierbarer Cloud-nativer Java-Anwendungen leistet GraalVM einen entscheidenden Beitrag zur Optimierung der Ressourcennutzung und zur Förderung der Kosteneffizienz. Im Wesentlichen spielt es eine entscheidende Rolle bei der Steigerung der Leistung und finanziellen Effizienz von Softwarelösungen in modernen, dynamischen Umgebungen.
1. Großer Speicherbedarf
Technische Auswirkungen
Herkömmliche JVM-basierte Dienste verursachen aufgrund des Klassenladens und der Metadaten für geladene Klassen häufig einen erheblichen Speicheraufwand.
Finanzfall
Ein hoher Speicherverbrauch führt zu höheren Infrastrukturkosten. Die Eliminierung von Metadaten für geladene Klassen und andere Optimierungen durch GraalVM führen zu einer effizienteren Nutzung von Ressourcen, was zu potenziellen Kosteneinsparungen führt.
2. Verlängerte Startzeiten
Technische Auswirkungen
Kaltstarts in Microservices können zu längeren Reaktionszeiten führen, die Benutzererfahrung beeinträchtigen und möglicherweise zu einer Verschlechterung des Dienstes führen.
Finanzfall
Längere Startzeiten wirken sich nicht nur auf die Benutzerzufriedenheit aus, sondern tragen auch zu höheren Betriebskosten bei. Die Optimierungen von GraalVM, wie die Eliminierung des Klassenladeaufwands und die Vorgenerierung des Image-Heaps während des Builds, reduzieren die Startzeiten drastisch und minimieren möglicherweise die Betriebskosten.
3. Hohe CPU-Auslastung
Technische Auswirkungen
Herkömmliche JVMs beanspruchen während des Startvorgangs häufig CPU-Zyklen für die Profilerstellung und die Just-In-Time-Kompilierung (JIT).
Finanzfall
Eine übermäßige CPU-Auslastung führt zu höheren Kosten für die Cloud-Infrastruktur. Die Vermeidung von Profiling- und JIT-ing-Overhead durch GraalVM trägt direkt zu einem reduzierten CPU-Verbrauch bei, was zu potenziellen Kosteneinsparungen bei der Cloud-Nutzung führt.
Microservices, insbesondere in serverlosen oder containerisierten Umgebungen, sind häufig mit dem Kaltstartproblem konfrontiert, das sich auf die Reaktionszeiten und die Benutzererfahrung auswirkt. GraalVM begegnet dieser Herausforderung durch die Implementierung mehrerer Optimierungen:
1. Kein Klassenladeaufwand
Herkömmliche Java-Anwendungen verlassen sich auf das Laden von Klassen zur Laufzeit, um Klassen dynamisch zu laden und zu verknüpfen. Dieser Prozess verursacht einen Mehraufwand, insbesondere während der Startphase. GraalVM minimiert diesen Overhead durch einen Prozess, der als statische oder AOT-Kompilierung (Ahead-of-Time) bezeichnet wird. Dazu gehört das Vorladen, Verknüpfen und teilweise Initiieren aller Klassen, die die Anwendung benötigt. Daher ist während des Anwendungsstarts kein Laden der Laufzeitklassen erforderlich.
2. Eliminierung von interpretiertem Code
Traditionelle Java Virtual Machines verlassen sich auf einen interpretierten Ausführungsmodus, bevor sie die Just-In-Time-Kompilierung (JIT) anwenden. Dies kann zu Startverzögerungen und erhöhter CPU-Auslastung führen. Native ausführbare Dateien enthalten keinen interpretierten Code, was zusätzlich zu schnelleren Startzeiten beiträgt.
3. Kein Profiling- und JIT-ing-Overhead
GraalVM bypasses the need to start the Just-In-Time (JIT) Compiler, reducing CPU usage during startup.
4. Image Heap Generation at Build Time
GraalVM's native image utility enables the execution of initialization processes for specific classes during the build process. This results in the generation of an image heap that includes pre-initialized portions, speeding up the application's startup.
Oracle GraalVM's native image utility has demonstrated startup times almost 100 times faster than traditional JVM-based applications. The graph below illustrates the substantial reduction in runtime memory requirements, showcasing GraalVM's efficiency compared to HotSpot(Figure 1).
Figure 1 – Native executables start up almost instantly(oracle.com)
GraalVM contributes to lower memory footprints through the following optimizations:
1. No Metadata for Loaded Classes
GraalVM avoids storing metadata for dynamically loaded classes in the non-heap memory. During the build process, the necessary class information is pre-loaded and linked, minimizing the need for additional metadata at runtime.
2. No Profiling Data or JIT Optimizations
Since the bytecode is already in native code, GraalVM eliminates the need for collecting profiling data for JIT optimizations, reducing memory overhead.
3. Isolation Technology
GraalVM introduces Isolates, a technology that partitions the heap into smaller, independent "heaps", enhancing efficiency, particularly in request processing scenarios.
In common, it consumes up to x5 times less memory compared to running on a JVM(Figure 2)
Figure 2 – Native executables memory compared to Go or Java HotSpot(oracle.com)
In conclusion, GraalVM's native image utility offers a transformative solution to the challenges posed by microservices, addressing startup time, memory footprint, and CPU usage concerns. By adopting GraalVM, developers can create cloud-native Java applications that are not only efficient and secure but also provide a superior user experience.
To compile your Quarkus service into a native image, various methods are available. While this article won't delve deeply into the Quarkus native build procedure, it does provide an overview of the essential steps.
Before proceeding with any approach for building a native image, it's crucial to set up the proper native profile in your pom.xml file. Add the following profile:
native native
Producing a Native Executable with Installed GraalVM
Check your GraalVM version using the following command:
./gu info native-image
This command will display the installed GraalVM version:
Downloading: Component catalog from www.graalvm.org Filename : https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.3.0/native-image-installable-svm-java19-linux-amd64-22.3.0.jar Name : Native Image ID : native-image Version : 22.3.0 GraalVM : 22.3.0 Stability: Experimental Component bundle native-image cannot be installed - The same component Native Image (org.graalvm.native-image[22.3.0.0/55b341ca1bca5219aafa8ed7c8a2273b81d184dd600d8261c837fc32d2dedae5]) is already installed in version 22.3.0
And to create a native executable, use:
./mvnw install -Dnative
These commands generate a *-runner binary in the target directory, allowing you to run the native executable:
./target/*-runner
Creating a Native Executable without installed GraalVM
If installing GraalVM locally poses challenges, an in-container build can be used:
./mvnw install -Dnative -Dquarkus.native.container-build=true -Dquarkus.native.builder-image=graalvm
This command initiates the build within a Docker container and provides the necessary image file. You can then start the application with:
./target/*-runner
In cases where building the native image proves challenging, the RedHat team provides a specialized distribution of GraalVM designed for the Quarkus framework called Mandrel. Mandrel streamlines
GraalVM, focusing solely on the native-image capabilities essential for Quarkus applications. To use Mandrel, follow these steps:
Identify the appropriate Mandrel version Mandrel repository
Set the Mandrel version in your application.properties file:
quarkus.native.builder-image=quay.io/quarkus/ubi-quarkus-mandrel-builder-image:23.0.1.2-Final-java17
3.Run the Maven build command:
./mvnw clean install -Pnative
For those who prefer manual control over container creation, a multi-stage Docker build can be employed.
FROM quay.io/quarkus/ubi-quarkus-mandrel-builder-image:23.0.1.2-Final-java17 AS build COPY --chown=quarkus:quarkus mvnw /app/mvnw COPY --chown=quarkus:quarkus .mvn /app/.mvn COPY --chown=quarkus:quarkus pom.xml /app/ USER quarkus WORKDIR /app RUN ./mvnw -B org.apache.maven.plugins:maven-dependency-plugin:3.6.1:go-offline COPY src /app/src RUN ./mvnw package -Dnative FROM quay.io/quarkus/quarkus-micro-image:2.0 WORKDIR /app/ COPY --from=build /app/target/*-runner /app/application RUN chmod 775 /app /app/application \ && chown -R 1001 /app \ && chmod -R "g+rwX" /app \ && chown -R 1001:root /app EXPOSE 8080 USER 1001 CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
This Dockerfile orchestrates a multi-stage build, resulting in a Docker image with your Quarkus application. Execute this Dockerfile to produce the Docker image, ready to run your Quarkus application.
GraalVM Native Image is a powerful technology that can revolutionize the way you develop and deploy Java microservices. By adopting GraalVM Native Image, you can create microservices that are:
GraalVM Native Image is a key enabler of cloud-native Java development and can help you achieve the performance, scalability, and cost savings that your business demands.
The above is the detailed content of Turbocharge Java Microservices with Quarkus and GraalVM Native Image. For more information, please follow other related articles on the PHP Chinese website!