Ich habe versucht, Dapr in Java zu verwenden, um die Entwicklung von Mikroservices zu erleichtern

Einführung

Mit Blick auf Microsoft Build 2020 schien Dapr von Distributed Application Runtime interessant zu sein. Tutorial war Node.js, daher habe ich ein Beispiel mit Dapr von Quarkus erstellt, während ich mich darauf bezog.

Code siehe unten https://github.com/koduki/example-dapr/tree/v01/api-with-java

Was ist Dapr?

Dapr ist ein von Microsoft entwickeltes Framework, das die Implementierung von Microservices vereinfacht, indem nicht funktionale Anforderungen wie Inter-Service-Aufruf, Statusverwaltung und Inter-Service-Messaging mit einem Side Car (Proxy) implementiert werden. Da es von OSS entwickelt wurde, kann es wie folgt verwendet werden.

Ich dachte, es sei dasselbe wie ein Service-Mesh wie Istio, weil es ein Seitenwagen war, aber als ich mir die Sitzung anhörte, fühlte es sich etwas anders an, abstrahierte Dateien und Statusverwaltung (Datenpersistenz) oder Warteschlangen wie Kafka. Es schien eine Rolle zu spielen. Wenn überhaupt, fühlt es sich wie JNDI von Java EE, DataSource oder JCA (Java Connector Architecture) an. ~~ Wenn du ein Onkel bist ~~ Es ist eine Chance zu sagen: "Dies ist die, die ich bei Shinkenzemi gemacht habe!"

Wenn es sich um einen Java EE-Container wie Weblogic handelt, befindet sich dieser Bereich meiner Meinung nach im selben Speicherbereich oder spricht in erster Linie mit T3, aber Dapr und jede Anwendung sprechen mit HTTP oder gRPC.

Lassen Sie uns Dapr vorerst verschieben

Verschieben wir es vorerst, bevor wir das eigentliche Tutorial machen. Da gRPC diesmal problematisch ist, werden wir REST implementieren. Erstellen Sie vorerst eine Quarkus-Vorlage mit dem Befehl mvn und führen Sie sie aus.

$ mvn io.quarkus:quarkus-maven-plugin:1.4.2.Final:create \
    -DprojectGroupId=dev.nklab \
    -DprojectArtifactId=dapr-app \
    -DprojectVersion=1.0.0-SNAPSHOT \
    -DclassName="dev.nklab.example.dapr.HelloResource"
$ cd dapr-app
$ ./mvnw quarkus:dev 

Versuchen Sie, von einem anderen Terminal aus mit Curl zuzugreifen.

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

Installieren Sie Dapr, wenn Sie den Betrieb der Anwendung bestätigen können. k8s funktioniert ohne spezielle Funktionen, aber Docker muss anscheinend im Voraus installiert werden.

$ curl -fsSL https://raw.githubusercontent.com/dapr/cli/master/install/install.sh | /bin/bash
$ dapr init

Die Installation ist nun abgeschlossen. Wenn Sie die folgende Fehlermeldung erhalten, haben Sie wahrscheinlich "dapr init" vergessen.

exec: "daprd": executable file not found in $PATH

Schließen Sie als Nächstes die zuvor mit Dapr erstellte Quarkus-Anwendung mit dem folgenden Befehl ab und führen Sie sie aus.

$ dapr run --app-id javaapp --app-port 8080 --port 3500 ./mvnw quarkus:dev 
...
ℹ️  Updating metadata for app command: ./mvnw quarkus:dev
✅  You're up and running! Both Dapr and your app logs will appear here.

--app-port ist die Quarkus-Portnummer und --port ist die Dapr-Portnummer. Lassen Sie uns mit Curl auf Dapr zugreifen.

$ curl http://localhost:3500/v1.0/invoke/javaapp/method/hello                                
hello

Da Dapr als Seitenwagen fungiert, dh als Proxy, können Sie sehen, dass Sie mit "3500" anstelle von "8080" auf die Backside-App zugreifen können. Der javaapp Teil ist die zur Laufzeit angegebene aap-id. Es scheint, dass es sich um einen Prozess handelt, der mit "invoke" mit der Anwendung auf der Rückseite verknüpft ist.

Zustandsverwaltung mit Redis

Anwendungsspezifikationen

Führen Sie nun die Schritte 1 bis 5 von [Hello World] aus (https://github.com/dapr/samples/tree/master/1.hello-world). Die diesmal zu implementierende Anwendung hat die folgende Struktur.

image.png

Der Benutzer sendet eine Anfrage an Application (Java) über Dapr, ruft die Dapr-API aus der Anwendung auf und schreibt über Dapr an Redis. Es ist interessant, Redis für die Datenpersistenz nicht direkt zu kontaktieren, da die Anwendung nur mit Dapr kommuniziert.

Als Spezifikation sendet der Benutzer die folgende POST-Anforderung an die Anwendung.

{
  "data": {
    "orderId": "42"
  } 
}

Diese Daten werden in Redis im folgenden Format gespeichert:

[{
  key: "order",
  value:Bestell-ID hier speichern
}]

Wenn eine GET-Anforderung an Application gesendet wird, wird die aktuelle orderId zurückgegeben.

Anwendungsimplementierung

Jetzt implementieren wir die Anwendung. Dieses Mal werden wir JSON verwenden, also fügen Sie die Bibliothek zu Quarkus hinzu.

$ ./mvnw quarkus:add-extension -Dextensions="quarkus-resteasy-jsonb"
$ ./mvnw quarkus:add-extension -Dextensions="quarkus-resteasy-jackson"

Ändern Sie dann die Anwendung wie folgt:

HelloResource.java


@Path("/")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class HelloResource {

    @ConfigProperty(name = "daprapp.daprport")
    String daprPort;

    String stateStoreName = "statestore";

    @GET
    @Path("/order")
    public Map<String, Object> order() throws IOException, InterruptedException {
        return Map.of("orderId", get(stateUrl() + "/order").body());
    }

    @POST
    @Path("/neworder")
    public HttpResponse neworder(Map<String, Map<String, Object>> data) throws IOException, InterruptedException {
        System.out.println("orderId: " + data.get("data").get("orderId"));

        var items = List.of(Map.of("key", "order", "value", data.get("data").get("orderId")));
        return post(stateUrl(), items);
    }

    private String stateUrl() {
        return "http://localhost:" + daprPort + "/v1.0/state/" + stateStoreName;
    }

    private HttpResponse<String> post(String url, List<Map<String, Object>> items) throws IOException, InterruptedException, JsonProcessingException {
        var mapper = new ObjectMapper();
        var client = HttpClient.newHttpClient();
        var request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .POST(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(items)))
                .setHeader("Content-Type", "application/json")
                .build();
        return client.send(request, HttpResponse.BodyHandlers.ofString());
    }

    private HttpResponse<String> get(String url) throws InterruptedException, IOException {
        var client = HttpClient.newHttpClient();
        var request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .GET()
                .setHeader("Content-Type", "application/json")
                .build();
        return client.send(request, HttpResponse.BodyHandlers.ofString());
    }
}

Ich habe als JAX-RS nichts Besonderes gemacht, daher werde ich nicht auf Details eingehen, aber "neworder" ist der Endpunkt für die Registrierung und "order" ist der Endpunkt als Referenz.

Sie greifen in jeder Methode auf "http: // localhost: 3500 / v1.0 / state / statestore" zu. Dies ist der Endpunkt der Statusverwaltungs-API von Dapr. Diesmal ist Redis die Substanz dieser Statusverwaltungs-API. Die Anforderung und Antwort der Statusverwaltungs-API lautet wie oben beschrieben wie folgt: JSON.

[{
  key:Wert,
  value:Wert
}]

Stellen Sie Redis für die Implementierung der Statusverwaltung ein

Stellen Sie dann Redis so ein, dass die Statusverwaltung implementiert wird. Es wurde jedoch bereits festgelegt. Überprüfen Sie es einfach. Tatsächlich wird zum Zeitpunkt von "dapr run" ein Verzeichnis mit dem Namen "components" erstellt. Es scheint, dass der statestore.yaml hier beschreibt, mit welchem Speicher eine Verbindung hergestellt werden soll.

components/statestore.yaml


apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
spec:
  type: state.redis
  metadata:
  - name: redisHost
    value: localhost:6379
  - name: redisPassword
    value: ""
  - name: actorStateStore
    value: "true"

Wenn Sie dies in RDB usw. umschreiben, handelt es sich möglicherweise um eine andere Implementierung.

Prüfung

Nachdem die Implementierung abgeschlossen ist, überprüfen wir den Vorgang. Starten Sie zuerst Dapr.

$ dapr run --app-id javaapp --app-port 8080 --port 3500 ./mvnw quarkus:dev

Dann stellen Sie eine Anfrage.

$ curl -X POST -H "Content-Type: application/json" -d '{"data": { "orderId": "41" } }' http://localhost:3500/v1.0/invoke/javaapp/method/neworder
{}
$ curl http://localhost:3500/v1.0/invoke/javaapp/method/order
{"orderId":"\"41\""}

Ich denke, Sie können bestätigen, dass der angeforderte Wert, den Sie geworfen haben, gespeichert ist und Sie können ihn erhalten. Sie können POST auch mit dem Befehl Dapr wie folgt schreiben.

$ dapr invoke --app-id javaapp --method neworder --payload '{"data": { "orderId": "41" } }'

Zusammenfassung

Vorerst habe ich versucht, Dapr aus Java zu verwenden. Da es sich um REST handelt, konnte ich es problemlos implementieren. Dapr hat immer noch ein Java EE-Gefühl mehr als Istio, und abgesehen von Dapr selbst scheint diese Idee unter dem Gesichtspunkt der einfachen Entwicklung in die richtige Richtung zu gehen. Die Grundidee besteht darin, die Substanz von Diensten und Daten, einschließlich des DAO-Musters, zu verbergen, und es ist besser, Nichtfunktionen so weit wie möglich in die Infrastruktur zu integrieren.

Wenn andererseits die Persistenzschicht auch Proxy durchläuft, scheint ein gewisser Overhead unvermeidlich zu sein, selbst wenn gRPC verwendet wird. Ich denke, dass es in Zukunft erforderlich sein wird, wie man mit diesem Bereich beabsichtigt umgeht.

Dapr selbst steckt noch in den Kinderschuhen und es gibt viele Ecken und Kanten, aber ich möchte es in Zukunft noch ein wenig berühren.

Viel Spaß beim Hacken!

Referenzlink

Recommended Posts

Ich habe versucht, Dapr in Java zu verwenden, um die Entwicklung von Mikroservices zu erleichtern
Ich habe versucht, JWT in Java zu verwenden
Ich habe versucht, Alexa-Fähigkeiten mit Java zu erstellen
Ich habe versucht, mit AI "A3RT" eine Talk-App in Java zu erstellen.
Ich habe versucht, Java REPL zu verwenden
Ich habe versucht, Metaprogrammierung mit Java
Ich habe versucht, eine Datenbankverbindung in der Android-Entwicklung zu verwenden
Ich habe versucht, die Firebase-Push-Benachrichtigung in Java zu implementieren
Ich habe versucht, SQS mit AWS Java SDK zu betreiben
# 2 [Anmerkung] Ich habe versucht, neunundneunzig mit Java zu berechnen.
Ich habe versucht, eine Clova-Fähigkeit in Java zu erstellen
Ich habe versucht, eine Anmeldefunktion mit Java zu erstellen
Ich habe versucht, die erweiterte for-Anweisung in Java zu verwenden
Ich habe versucht, die Methode der gegenseitigen Teilung von Eugrid in Java zu implementieren
~ Ich habe jetzt versucht, funktionale Programmierung mit Java zu lernen ~
Ich habe versucht herauszufinden, was sich in Java 9 geändert hat
Ich habe versucht, mit Chocolatey eine Java8-Entwicklungsumgebung zu erstellen
Ich habe versucht, die Java8 Stream API zu verwenden
Ich habe versucht, in Java von einer Zeichenfolge in einen LocalDate-Typ zu konvertieren
Ich habe versucht, das Java-Lernen zusammenzufassen (1)
Ich habe einen RESAS-API-Client in Java erstellt
Ich habe jetzt versucht, Java 8 zusammenzufassen
Ich habe versucht, Java Memo LocalDate zu verwenden
Ich habe versucht, Google HttpClient von Java zu verwenden
Ich habe versucht, Java-Anfänger so einzustellen, dass sie Tastenkombinationen in Eclipse verwenden
Ich habe versucht, den Kalender mit Java auf der Eclipse-Konsole anzuzeigen.
Ich habe versucht, Java-Lambda-Ausdrücke zusammenzufassen
Ich habe versucht, OpenCV mit Java + Tomcat zu verwenden
[Für Anfänger] Ich habe versucht, DBUnit mit Eclipse zu verwenden
Ich habe versucht, eine Standardauthentifizierung mit Java durchzuführen
Ich habe versucht, polymorph in Nogizaka zu implementieren.
[Für Anfänger] Ich habe versucht, JUnit 5 mit Eclipse zu verwenden
Ich möchte eine E-Mail in Java senden.
Ich habe versucht, die Sitzung in Rails zu organisieren
Java Ich habe versucht, einen einfachen Block zu brechen
rsync4j - Ich möchte rsync in Java berühren.
Ich habe versucht, eine Anwendung in 2 Sprachen zu entwickeln
Ich habe versucht, einen Server mit Netty zu implementieren
Ich habe versucht, den Block mit Java zu brechen (1)
[Hinweis] Java-Programm in integrierter Entwicklungsumgebung ausführen Eclipse-I hat versucht, git zu verwenden
[Java] Ich habe versucht, über den Verbindungspool eine Verbindung mit Servlet (Tomcat) & MySQL & Java herzustellen
Ich habe versucht, Gson zu benutzen
Ich habe versucht, TestNG zu verwenden
Ich habe versucht, Galasa zu benutzen
Ich möchte so etwas wie "cls" in Java machen
Ich habe versucht, TCP / IP + BIO mit JAVA zu implementieren
Ich möchte ES2015 auch in Java verwenden! → (´ ・ ω ・ `)
Dinge, auf die Sie bei der zukünftigen Java-Entwicklung achten sollten
Ich habe versucht, Log4j2 auf einem Java EE-Server zu verwenden
Ich habe versucht, Sterling Sort mit Java Collector zu implementieren
[Java] Ich habe versucht, die Yahoo API-Produktsuche zu implementieren
Ich habe versucht, Java Silver in 2 Wochen zu bestehen, ohne Java zu kennen
Versuchen Sie, mit Docker eine Java-Entwicklungsumgebung zu erstellen
Ich habe versucht, ein Aktienchart mit Java (Jsoup) zu kratzen.
Ich habe versucht, Effective Java 3rd Edition "fast alle Kapitel" in "leicht lesbarem Japanisch" zu erklären.