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
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.
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.
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.
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.
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 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.
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" } }'
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!
Recommended Posts