J'ai essayé d'utiliser Dapr en Java pour faciliter le développement de microservices

introduction

En regardant Microsoft Build 2020, Dapr of Distributed Application Runtime semblait intéressant. Tutoriel était Node.js, j'ai donc créé un échantillon en utilisant Dapr de Quarkus tout en y faisant référence.

Voir ci-dessous pour le code https://github.com/koduki/example-dapr/tree/v01/api-with-java

Qu'est-ce que Dapr?

Dapr est un framework développé par Microsoft qui simplifie la mise en œuvre des microservices en implémentant des exigences non fonctionnelles telles que l'invocation inter-service, la gestion d'état et la messagerie inter-service avec un side car (Proxy). Puisqu'il est développé par OSS, il peut être utilisé à partir de ce qui suit.

Je pensais que c'était la même chose qu'un service mesh tel qu'Istio parce que c'était une side car, mais quand j'écoutais la session, c'était un peu différent, en faisant abstraction des fichiers et de la gestion de l'état (persistance des données), ou en mettant en file d'attente comme Kafka. Il semblait y avoir un rôle à jouer. Si quoi que ce soit, cela ressemble à JNDI de Java EE, DataSource ou JCA (Java Connector Architecture). ~~ Si vous êtes un oncle ~~ C'est une chance de dire: "C'est celui que j'ai fait à Shinkenzemi!"

S'il s'agit d'un conteneur Java EE tel que Weblogic, je pense que cette zone est dans le même espace mémoire et parle avec T3 en premier lieu, mais Dapr et chaque application parlent avec HTTP ou gRPC.

Déplaçons Dapr pour le moment

Déplaçons-le pour le moment avant de faire le tutoriel proprement dit. Puisque gRPC est gênant cette fois, nous allons implémenter REST. Pour le moment, créez un modèle Quarkus avec la commande mvn et exécutez-le.

$ 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 

Essayez d'accéder avec curl depuis un autre terminal.

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

Installez Dapr lorsque vous pouvez confirmer le fonctionnement de l'application. k8s fonctionne sans aucune particularité, mais Docker semble devoir être installé à l'avance.

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

L'installation est maintenant terminée. Si vous obtenez l'erreur suivante, vous avez probablement oublié dapr init.

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

Ensuite, enveloppez l'application Quarkus créée précédemment avec Dapr avec la commande suivante et exécutez-la.

$ 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 est le numéro de port Quarkus et --port est le numéro de port Dapr. Accédons à Dapr avec curl.

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

Puisque Dapr agit en tant que side car, c'est-à-dire Proxy, vous pouvez voir que vous pouvez accéder à l'application arrière avec 3500 au lieu de 8080. La partie javaapp est le ʻaap-id spécifié à l'exécution. Il semble que ce sera un processus lié à l'application au verso avec ʻinvoke.

Gestion des états à l'aide de Redis

Spécifications d'application

Maintenant, effectuez les étapes 1 à 5 de Hello World. L'application à implémenter cette fois a la structure suivante.

image.png

L'utilisateur envoie une demande à Application (Java) via Dapr, accède à l'API de Dapr depuis l'application et écrit dans Redis via Dapr. Il est intéressant de ne pas passer directement par Redis pour la persistance des données, car l'application ne parle qu'à Dapr.

En tant que spécification, l'utilisateur envoie la requête POST suivante à l'application.

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

Ces données sont stockées dans Redis au format suivant:

[{
  key: "order",
  value:Commande en magasinId ici
}]

En outre, lorsqu'une demande GET est envoyée à Application, le orderId actuel est renvoyé.

Implémentation de l'application

Maintenant, implémentons l'application. Cette fois, nous utiliserons JSON, alors ajoutez la bibliothèque à Quarkus.

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

Modifiez ensuite l'application comme suit:

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());
    }
}

Je n'ai rien fait de spécial en tant que JAX-RS, donc je vais omettre les détails, mais neworder est le point final pour l'enregistrement et ʻorder` est le point final pour référence.

Vous accédez à http: // localhost: 3500 / v1.0 / state / statestore dans chaque méthode. C'est le point final de l'API de gestion d'état de Dapr. Cette fois, la substance de cette API de gestion d'état est Redis. La demande et la réponse de l'API de gestion d'état seront le JSON suivant, comme décrit ci-dessus.

[{
  key:valeur,
  value:valeur
}]

Définir Redis pour la mise en œuvre de la gestion des états

Configurez ensuite Redis pour implémenter la gestion de l'état. Cependant, il a déjà été défini, alors vérifiez-le. En fait, un répertoire appelé «composants» est créé au moment de «l'exécution du dapr». Il semble que le statestore.yaml décrit ici à quel magasin se connecter.

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"

Peut-être que si vous réécrivez ceci dans RDB etc., ce sera une autre implémentation.

tester

Maintenant que l'implémentation est terminée, vérifions l'opération. Tout d'abord, démarrez Dapr.

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

Alors faites une demande.

$ 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\""}

Je pense que vous pouvez confirmer que la valeur demandée que vous avez lancée est stockée et que vous pouvez l'obtenir. Vous pouvez également écrire POST avec la commande Dapr comme suit.

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

Résumé

Pour le moment, j'ai essayé d'utiliser Dapr de Java. Puisqu'il s'agit de REST, j'ai pu l'implémenter sans aucun problème. Dapr a toujours un sentiment Java EE plus qu'Istio, et en dehors de Dapr lui-même, cette idée elle-même semble aller dans la bonne direction du point de vue de la facilité de développement. L'idée de base est de cacher la substance des services et des données, y compris le modèle DAO, et il vaut mieux intégrer autant que possible les non-fonctions dans l'infrastructure.

D'un autre côté, si la couche de persistance passe également par Proxy, il semble qu'une certaine surcharge soit inévitable même si gRPC est utilisé. Je pense qu'il sera nécessaire à l'avenir de savoir comment traiter ce domaine par conception.

Dapr lui-même en est encore à ses balbutiements et il y a de nombreuses aspérités, mais j'aimerais y toucher un peu plus à l'avenir.

Bon piratage!

Lien de référence

Recommended Posts

J'ai essayé d'utiliser Dapr en Java pour faciliter le développement de microservices
J'ai essayé d'utiliser JWT en Java
J'ai essayé de créer une compétence Alexa avec Java
J'ai essayé de créer une application de conversation en Java à l'aide de l'IA «A3RT»
J'ai essayé d'utiliser Java REPL
J'ai essayé la métaprogrammation avec Java
J'ai essayé d'utiliser une connexion à une base de données dans le développement Android
J'ai essayé d'implémenter la notification push Firebase en Java
J'ai essayé de faire fonctionner SQS en utilisant AWS Java SDK
# 2 [Note] J'ai essayé de calculer quatre-vingt-dix-neuf avec Java.
J'ai essayé de créer une compétence Clova en Java
J'ai essayé de créer une fonction de connexion avec Java
J'ai essayé d'utiliser l'instruction Extended for en Java
J'ai essayé d'implémenter la méthode de division mutuelle d'Eugrid en Java
~ J'ai essayé d'apprendre la programmation fonctionnelle avec Java maintenant ~
J'ai essayé de découvrir ce qui avait changé dans Java 9
J'ai essayé de créer un environnement de développement java8 avec Chocolatey
J'ai essayé d'utiliser l'API Java8 Stream
J'ai essayé de convertir une chaîne de caractères en un type LocalDate en Java
J'ai essayé de résumer l'apprentissage Java (1)
J'ai créé un client RESAS-API en Java
J'ai essayé de résumer Java 8 maintenant
J'ai essayé d'utiliser le mémo Java LocalDate
J'ai essayé d'utiliser Google HttpClient de Java
J'ai essayé de configurer les débutants Java pour qu'ils utilisent des touches de raccourci dans eclipse
J'ai essayé d'afficher le calendrier sur la console Eclipse en utilisant Java.
J'ai essayé de résumer les expressions Java lambda
J'ai essayé d'utiliser OpenCV avec Java + Tomcat
[Pour les débutants] J'ai essayé d'utiliser DBUnit avec Eclipse
J'ai essayé de faire une authentification de base avec Java
J'ai essayé d'implémenter des relations polymorphes à Nogizaka.
[Pour les débutants] J'ai essayé d'utiliser JUnit 5 avec Eclipse
Je souhaite envoyer un e-mail en Java.
J'ai essayé d'organiser la session en Rails
java j'ai essayé de casser un simple bloc
rsync4j --Je veux toucher rsync en Java.
J'ai essayé de développer une application en 2 langues
J'ai essayé d'implémenter un serveur en utilisant Netty
J'ai essayé de casser le bloc avec java (1)
[Note] Exécutez le programme java dans l'environnement de développement intégré Eclipse-J'ai essayé d'utiliser git
[Java] J'ai essayé de me connecter en utilisant le pool de connexion avec Servlet (tomcat) & MySQL & Java
J'ai essayé d'utiliser Gson
J'ai essayé d'utiliser TestNG
J'ai essayé d'utiliser Galasa
Je veux faire quelque chose comme "cls" en Java
J'ai essayé d'implémenter TCP / IP + BIO avec JAVA
Je veux aussi utiliser ES2015 avec Java! → (´ ・ ω ・ `)
Points à surveiller dans le développement futur de Java
J'ai essayé d'utiliser Log4j2 sur un serveur Java EE
J'ai essayé d'implémenter Sterling Sort avec Java Collector
[Java] J'ai essayé de mettre en œuvre la recherche de produits de l'API Yahoo
J'ai essayé de passer Java Silver en 2 semaines sans connaître Java
Essayez de créer un environnement de développement Java à l'aide de Docker
J'ai essayé de gratter un graphique boursier en utilisant Java (Jsoup)
J'ai essayé d'expliquer Effective Java 3rd Edition "presque tous les chapitres" en "japonais facile à lire".