Eine Übersicht über das native Java-Framework Quarkus von Kubernetes

Einführung

Am 7. März 2019 kündigte Red Hat das native Kubernetes-Java-Framework "Quarkus" an.

Introducing Quarkus: a next-generation Kubernetes native Java framework https://developers.redhat.com/blog/2019/03/07/quarkus-next-generation-kubernetes-native-java-framework/

Mit der Verwendung von Kubernetes und der Umstellung auf Microservices und Serverlosigkeit wird die Containerisierung von Anwendungen immer häufiger, und ein langsamer Start im Vergleich zu anderen Sprachen war ein großer Nachteil für Java. Auf der anderen Seite verfügt Quarkus über eine Catch-Kopie von "Supersonic Subatomic Java (Java kleiner als Atom)", indem die mit GraalVM erstellte Linux Native-Binärdatei auf dem Container gestartet wird. Dies reduziert die Java-Startzeit erheblich.

Ich denke, dass verschiedene Leute bereits Blogs über Quarkus geschrieben haben, daher werde ich in diesem Artikel auch über "Hintergrund des Erscheinungsbilds von Quarkus" und "Bereitstellen von Anwendungen mit Quarkus für Kubernetes" schreiben. ..

Hintergrund des Auftretens von Quarkus

Aufgrund der Popularität von Docker / Kubernetes und des Trends zu Microservices / Serverless wird die Containerisierung von Anwendungen immer häufiger. Für die Entwicklung dieser Containeranwendungen werden häufig leichtgewichtige Sprachen mit kurzer Startzeit und geringer Speichernutzung wie Golang und Ruby verwendet, und die Verwendung von Java mit langsamer Startzeit und großer Speichernutzung wurde vermieden. Ich tat.

Das Java-Ökosystem existiert jedoch seit über 20 Jahren und ist ab 2019 immer noch eine der beliebtesten Sprachen, die von vielen Entwicklern verwendet werden.

"Quarkus" wurde eingeführt, um native Containeranwendungen von Kubernetes unter Verwendung von Java bereitzustellen und dabei das Wissen und die Fähigkeiten zu nutzen, die Java-Entwickler bisher entwickelt haben. Quarkus kann die Startzeit erheblich verkürzen, die Speichernutzung reduzieren und kleine Container-Images erzielen.

Wir glauben, dass Quarkus veröffentlicht wurde, um viele Java-Entwickler in das Kubernetes-Ökosystem zu bringen und Containeranwendungen allgemeiner und das Kubernetes-Ökosystem größer zu machen. ..

Was ist GraalVM?

GraalVM ist eine universelle Laufzeit, die von Oracle im April 2018 als Open Source veröffentlicht wurde und die Ausführung mehrerer Sprachen wie Java, JavaScript, Ruby und Python auf einer einzigen integrierten Laufzeit ermöglicht.

architecture.png

Zitat: https://www.graalvm.org/docs/img/architecture.png

Für Java-Anwendungsentwickler ermöglicht die neue Just-In-Time-Kompilierungstechnologie, dass Java-Anwendungen schneller ausgeführt werden. GraalVM bietet auch die Möglichkeit, native Binärdateien zu erstellen, eine Maschine, die sofort mithilfe einer statischen Analyse ausgeführt werden kann, um erreichbaren Code zu finden und eine AOT-Kompilierung (Ahead-Of-Time) durchzuführen. Sie können den Code in eine native Binärdatei aufnehmen.

Einschränkungen ab März 2019

Support- / Nicht-Support-Status der CDI-Implementierung

In Quarkus kann CDI (Contexts and Dependency Injection) verwendet werden, es können jedoch nicht alle CDI-Spezifikationen implementiert werden. Die unterstützten und nicht unterstützten Funktionen sind wie folgt.

Unterstützte Funktionen

Beschränkungen

Referenz: https://quarkus.io/guides/cdi-reference.html

Bauzeit

Quarkus verwendet GraalVM, um eine native Binärdatei für Linux zu erstellen. In meiner Umgebung dauert es jedoch "9 Minuten" von der Ausführung des Maven-Befehls bis zur Ausführung, obwohl es sich um eine einfache Anwendung handelt. Es ist weg. Da der "Entwicklungsmodus", der die Hot-Bereitstellung realisiert, bereitgestellt wird, wird er bei der Entwicklung in einer lokalen Umgebung nicht containerisiert, sondern vorerst im "Entwicklungsmodus" entwickelt.

Lassen Sie uns die Anwendung mit Quarkus auf Kubernetes bereitstellen

Hier erstellen wir eine einfache JAX-RS-Anwendung, indem wir den unter der folgenden URL eingeführten ersten Schritten folgen.

QUARKUS - GET STARTED https://quarkus.io/get-started/

getting-started-architecture.png

Vorbereitungen

Um eine Anwendung mit Quarkus auf Kubernetes bereitzustellen, müssen Sie die folgende Umgebung im Voraus vorbereiten.

Erste Anwendung erstellen

Lassen Sie uns ein Maven-Projekt erstellen

Um eine Anwendung mit Quarkus zu entwickeln, erstellen Sie ein Maven-Projekt mit dem folgenden Befehlsbeispiel.

mvn io.quarkus:quarkus-maven-plugin:0.11.0:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=getting-started \
    -DclassName="org.acme.quickstart.GreetingResource" \
    -Dpath="/hello"

Wenn Sie den obigen Befehl ausführen, wird eine Verzeichnisdatei erstellt, die der folgenden ähnelt: Hier wird auch automatisch eine Docker-Beispieldatei im Verzeichnis src / main / docker erstellt.

$ tree getting-started/
getting-started/
├── pom.xml
└── src
    ├── main
    │   ├── docker
    │   │   └── Dockerfile
    │   ├── java
    │   │   └── org
    │   │       └── acme
    │   │           └── quickstart
    │   │               └── GreetingResource.java
    │   └── resources
    │       └── META-INF
    │           ├── microprofile-config.properties
    │           └── resources
    │               └── index.html
    └── test
        └── java
            └── org
                └── acme
                    └── quickstart
                        ├── GreetingResourceTest.java
                        └── NativeGreetingResourceIT.java

Quarkus BOM und Quarkus-Maven-Plugin sind in der automatisch generierten pom.xml wie unten gezeigt vorkonfiguriert.

pom.xml


<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-bom</artifactId>
            <version>${quarkus.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<build>
    <plugins>
        <plugin>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-maven-plugin</artifactId>
            <version>${quarkus.version}</version>
            <executions>
                <execution>
                    <goals>
                        <goal>build</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Lassen Sie uns den Code der Anwendung überprüfen

Wenn Sie ein Maven-Projekt mit dem obigen Befehl erstellen, wird der folgende Beispielcode generiert.

src/main/java/org/acme/quickstart/GreetingResource.java


package org.acme.quickstart;
  
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class GreetingResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hello";
    }
}

Beginnen wir im Entwicklungsmodus

Versuchen Sie als Nächstes, die Anwendung im "Entwicklungsmodus" zu starten. Im "Entwicklungsmodus" ist eine Hot-Bereitstellung durch Hintergrundkompilierung möglich. Wenn Sie die Java-Datei aktualisieren und den Browser aktualisieren, wird die Java-Datei automatisch kompiliert und Sie können die geänderte Anwendung überprüfen.

$ mvn compile quarkus:dev

Sie können den Betrieb der JAX-RS-Beispielanwendung überprüfen, indem Sie den folgenden Befehl ausführen.

$ curl http://localhost:8080/hello
hello

Versuchen wir es mit CDI (Contexts and Dependency Injection).

Als nächstes passen wir die automatisch generierte Beispielanwendung an. Erstellen Sie hier eine neue Serviceklasse und fügen Sie der automatisch generierten Datei GreetingResource.java einen Serviceklassenaufruf hinzu.

Fügen Sie die folgende Serviceklasse neu hinzu.

src/main/java/org/acme/quickstart/GreetingService.java


package org.acme.quickstart;
  
import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class GreetingService {

    public String greeting(String name) { 
        return "hello " + name;
    }

}

Ändern Sie dann die automatisch generierte Datei GreetingResource.java.

src/main/java/org/acme/quickstart/GreetingResource.java


package org.acme.quickstart;
  
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.inject.Inject;
import javax.ws.rs.PathParam;

@Path("/hello")
public class GreetingResource {

    @Inject
    GreetingService service;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/greeting/{name}")
    public String greeting(@PathParam("name") String name) {
        return service.greeting(name);
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hello";
    }
}

Überprüfen Sie den Vorgang mit dem folgenden Befehl.

$ curl http://localhost:8080/hello/greeting/quarkus
hello quarkus

Erstellen einer nativen Linux-Binärdatei

Lassen Sie uns eine native Binärdatei generieren

Als Nächstes verwende ich GraalVM, um eine native Binärdatei für Linux zu erstellen. Die automatisch generierte Datei pom.xml enthält im Profil vorkonfigurierte Ausführungen. Mit den folgenden Einstellungen können Sie eine Linux Native-Binärdatei erstellen, indem Sie den Befehl Maven ausführen.

pom.xml


<profiles>
    <profile>
        <id>native</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>io.quarkus</groupId>
                    <artifactId>quarkus-maven-plugin</artifactId>
                    <version>${quarkus.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>native-image</goal>
                            </goals>
                            <configuration>
                                <enableHttpUrlHandler>true</enableHttpUrlHandler>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

Erstellen Sie eine native Linux-Binärdatei mit dem folgenden Maven-Befehl.

$ mvn package -Pnative -Dnative-image.docker-build=true

Hier ist die Option "-Pnative" eine Option zum Generieren einer Binärdatei, die von Native ausgeführt werden kann, und die Option "-Dnative-image.docker-build = true" ist eine Option zum Generieren einer Native-Binärdatei, die dem Betriebssystem in Docker entspricht. Dies ist eine Option, die erforderlich ist, um dies explizit zu machen.

Übrigens, als ich es in meiner Umgebung ausführte, dauerte es "ungefähr 9 Minuten", um den Maven-Befehl auszuführen. Wenn es so lange dauert, bis Docker Build ausgeführt wird, ist es nicht möglich, häufig zu erstellen. Daher würde ich gerne zukünftige Funktionsverbesserungen erwarten.

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 08:48 min
[INFO] Finished at: 2019-03-18T12:16:35+09:00
[INFO] ------------------------------------------------------------------------

Lassen Sie uns Docker bauen

containerization-process.png

Wenn Sie ein Maven-Projekt erstellen, wird automatisch eine Docker-Beispieldatei generiert. Erstellen Sie daher ein Docker-Image basierend auf dieser Datei.

FROM registry.fedoraproject.org/fedora-minimal
WORKDIR /work/
COPY target/*-runner /work/application
RUN chmod 775 /work
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]

Erstellen Sie ein Docker-Image mit dem folgenden Befehl.

$ docker build -f src/main/docker/Dockerfile -t quarkus-quickstart/quickstart .

Lassen Sie uns die Größe des erstellten Container-Images überprüfen. Da das Basis-Image "Fedra-Minimal" ist, sind es 125 MB. Wenn Sie jedoch nur die Quarkus-JAX-RS-Beispielanwendung ausführen, können Sie an dem Unterschied erkennen, dass es "etwa 20 MB" beträgt. In Anbetracht der Zeit, in der Hunderte von MB für die Installation des JDK benötigt wurden, sieht diese Container-Image-Größe recht klein aus.

$ docker images
REPOSITORY                                  TAG                 IMAGE ID            CREATED              SIZE
quarkus-quickstart/quickstart               latest              d93d89bde0bb        About a minute ago   125MB
registry.fedoraproject.org/fedora-minimal   latest              f0c38118c459        3 weeks ago          105MB

Lassen Sie uns die Operation überprüfen

Versuchen Sie als Nächstes, den Docker-Container zu starten.

$ docker run -i --rm -p 8080:8080 quarkus-quickstart/quickstart
2019-03-18 03:21:00,052 INFO  [io.quarkus](main) Quarkus 0.11.0 started in 0.012s. Listening on: http://0.0.0.0:8080
2019-03-18 03:21:00,054 INFO  [io.quarkus](main) Installed features: [cdi, resteasy]

In meiner Umgebung konnte ich es in einer dramatisch kurzen Zeit von "0,012 Sekunden" starten, was mit einer herkömmlichen Java-Anwendung wie im obigen Beispiel undenkbar ist. Sie können den Vorgang auch mit dem folgenden Befehl überprüfen.

curl http://localhost:8080/hello
hello

Die Speichernutzung ist wie folgt, und Sie können sehen, dass die JAX-RS-Beispielanwendung nur 1,2 MB verwendet.

$ docker stats
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
b4d39bbe3159        eloquent_bohr       0.00%               1.281MiB / 1.952GiB   0.06%               1.04kB / 0B         0B / 0B             5

Bereitstellung in Kubernetes

Bis zu diesem Punkt haben Sie mit dem Befehl Maven eine native Linux-Binärdatei aus dem Java-Quellcode erstellt und die Linux-Binärdatei als Container gestartet. Als nächstes möchte ich eine Anwendung mit Quarkus auf Kuberntetes (Minikube) bereitstellen.

Erstellen Sie Deployment / ReplicaSet / Pod-Ressourcen aus dem zuvor mit dem folgenden Befehl erstellten Docker-Image.

$ kubectl run quarkus-quickstart --image=quarkus-quickstart/quickstart:latest --port=8080 --image-pull-policy=IfNotPresent
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/quarkus-quickstart created

Erstellen Sie als Nächstes eine Serviceressource mit dem Befehl kubectl expose, damit Sie den Vorgang überprüfen können.

$ kubectl expose deployment quarkus-quickstart --type=NodePort
service/quarkus-quickstart exposed

Die mit den beiden obigen Befehlen erstellten Kubernetes-Ressourcen lauten wie folgt.

$ kubectl get all
NAME                                      READY   STATUS    RESTARTS   AGE
pod/quarkus-quickstart-7986c7cd95-44k9n   1/1     Running   1          1m

NAME                         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/kubernetes           ClusterIP   10.96.0.1      <none>        443/TCP          5m
service/quarkus-quickstart   NodePort    10.103.25.16   <none>        8080:32179/TCP   27s

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/quarkus-quickstart   1/1     1            1           1m

NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/quarkus-quickstart-7986c7cd95   1         1         1       1m

Sie können den Betrieb der auf Kubernetes (Minikube) bereitgestellten Quarkus-Anwendung mit dem folgenden Befehl überprüfen.

$ curl $(minikube service quarkus-quickstart --url)/hello/greeting/quarkus
hello quarkus

schließlich

In diesem Artikel schrieb ich über "Hintergrund des Erscheinungsbilds von Quarkus" und "Bereitstellen von Anwendungen mit Quarkus für Kubernetes". Wie oben erwähnt, beschleunigt Quarkus nicht nur den Start erheblich, sondern auch die wesentlichen Elemente für Containeranwendungen wie geringe Bildgröße und Speichernutzung befinden sich in Java, wo eine große Anzahl von Entwicklern, einschließlich Unternehmen, beschäftigt ist. Ich denke, es war eine sehr wichtige Veröffentlichung in dem Sinne, dass es möglich wurde.

Da es jedoch gerade veröffentlicht wurde, haben wir auch festgestellt, dass es verschiedene Einschränkungen für CDI gibt und dass die Erstellung sehr lange dauert.

Quarkus scheint ein von Red Hat veröffentlichtes Produkt zu sein und wurde als OSS (Open Source Software) entwickelt. Es wurde gerade veröffentlicht und ich denke, wir werden in Zukunft weitere Funktionen hinzufügen und verbessern, daher würde ich gerne weiter schauen.

Referenzinformationen

Recommended Posts

Eine Übersicht über das native Java-Framework Quarkus von Kubernetes
Ich habe das Java-Framework "Quarkus" ausprobiert.
Messen Sie die Größe eines Ordners mit Java
Awesome Java: Großartige Java Framework Library-Software
[Java] Beim Schreiben der Quelle ... Memorandum ①
Eine Übersicht über die Spring Framework Resource-Oberfläche
Eine Aufzeichnung über das Studium des Spring Framework von Grund auf neu
Eine kurze Erklärung der fünf Arten von Java Static
Denken Sie an eine Java-Update-Strategie
[Java] Löschen Sie die Elemente von List
Grundursache für Java Framework Bug
[Java Edition] Geschichte der Serialisierung
Liste der Java-Objekte sortieren
Ein Memorandum über das FizzBuzz-Problem
Überlegungen zum Java Persistence Framework 2017 (1)
Eine Geschichte über das Erreichen der League Of Legends-API mit JAVA
Rufen Sie die öffentliche URL der privaten Datei von Flickr in Java ab
Eine kurze Beschreibung der JAVA-Abhängigkeiten
Lassen Sie uns eine TODO-App in Java 5 erstellen. Schalten Sie die Anzeige von TODO um
Der Ursprung von Java-Lambda-Ausdrücken
Erhöhen Sie dynamisch die Anzahl der Elemente in einem zweidimensionalen Java-Array (mehrdimensionales Array).
Eine Sammlung von Phrasen, die das "unterschiedliche Gefühl" von Java und JavaScript beeindruckt
Die Geschichte eines Game Launcher mit automatischer Ladefunktion [Java]
Lassen Sie uns das Ergebnis der Analyse von Java-Bytecode in einem Klassendiagramm ausdrücken
So finden Sie heraus, welche Java-Version der Klassendatei kompiliert wurde
[Java] Wie man mit der String-Klasse an die Spitze eines bestimmten Strings kommt
Beispielprogramm, das den Hashwert einer Datei in Java zurückgibt
So ermitteln Sie den absoluten Pfad eines in Java ausgeführten Verzeichnisses
Nennen Sie eine Gruppe regulärer Ausdrücke (Java)
Überprüfen Sie den Inhalt des Java-Zertifikatspeichers
Untersuchen Sie die Speichernutzung von Java-Elementen
[Java] Ermittelt den Tag eines bestimmten Tages
Anmerkung: [Java] Überprüfen Sie den Inhalt des Verzeichnisses
Vergleichen Sie Elemente eines Arrays (Java)
Versuchen Sie, Kubernetes Job von Java aus auszuführen
[Tag: 5] Ich habe die Grundlagen von Java zusammengefasst
Was sind die aktualisierten Funktionen von Java 13
Messen Sie einfach die Größe von Java-Objekten
Rückblick auf die Grundlagen von Java
Ausgabe des Buches "Einführung in Java"
Funktionen des Spring Frameworks für Java-Entwickler
Übersicht über Java 8-Funktion, Verbraucher, Lieferant, Prädikat
Die Geschichte des Schreibens von Java in Emacs
[Java] Überprüfen Sie die Anzahl der Zeichen
Finden Sie den Unterschied von einem Vielfachen von 10
[Java] [Spring] Testen Sie das Verhalten des Loggers
Java-Framework
Bis zum Start eines Docker-Containers, der mit RedHat Quarkus erstellt wurde
Eine Geschichte, die die Implementierung der SendGrid-Java-Bibliothek bestätigt, wenn die E-Mail-Zustellung fehlschlägt
Überprüfen Sie das ID-Token eines von AWS Cognito in Java authentifizierten Benutzers
Die Geschichte des einfachen String-Vergleichs in Java
JAVA: jar, aar, zeige den Inhalt der Datei an
Die Geschichte eines gewöhnlichen Othello in Java
Über den offiziellen Startleitfaden für Spring Framework
Informationen zur Beschreibungsreihenfolge der Java-Systemeigenschaften
Über die Idee anonymer Klassen in Java
Benötigen Sie eine speicherbewusste Implementierung von Java?
Eine Geschichte über das JDK in der Java 11-Ära
Machen Sie einen Rand links vom TextField
Die Reihenfolge der Java-Methodenmodifikatoren ist festgelegt
[Java] Zugriff auf die signierte URL von s3 (signierte Version 2)