Skip to content
Snippets Groups Projects
Verified Commit f20ede1e authored by Julien Wittouck's avatar Julien Wittouck
Browse files

:sparkles: : add EDA practice

parent 8c7cea66
No related branches found
No related tags found
No related merge requests found
Pipeline #54659 passed
:source-highlighter: rouge
:prewrap!:
:icons: font
:toc: left
:toclevels: 4
:linkattrs:
:sectlinks:
:sectanchors:
:sectnums:
:experimental:
:stem:
= ALOM - TP 11 - EDA !
== Présentation et objectifs
Le but est de continuer le développement de notre architecture "à la microservice".
Nous allons utiliser Apache Pulsar, pour implémenter un début d'architecture EDA entre les micro-services game et mailing.
.Notre architecture !
image::images/pokemon-archi.png[]
== Pré-requis
En pré-requis à ce TP, il faut avoir implémenté la partie https://alom-2024.gitlabpages.univ-lille.fr/cours/w09-cloud/09-tp-cloud.html#_envoi_demails[6. Envoi d'emails, role="external", window="_blank"].
== `mailing-api`
=== Démarrage d'une instance locale de pulsar
Apache Pulsar est disponible sous la forme d'une image Docker : https://hub.docker.com/r/apachepulsar/pulsar[apachepulsar/pulsar, role="external", window="_blank"].
Démarrez une instance de pulsar sur votre poste avec la commande suivante :
[source,bash]
----
docker container run -d \
--name pulsar \
-p 6650:6650 \
-p 6080:8080 \
apachepulsar/pulsar:4.0.1 \
bin/pulsar standalone
----
=== Configuration Spring Boot
Dans votre projet `mailing`, importez la dépendance `spring-boot-starter-pulsar` :
[source,xml]
.pom.xml
----
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-pulsar</artifactId>
</dependency>
----
Configurez les properties suivantes dans un fichier `application-local.properties`, pour utiliser votre instance locale :
[source,properties]
.application-local.properties
----
spring.pulsar.client.service-url=pulsar://localhost:6650
spring.pulsar.admin.service-url=http://localhost:6080
----
=== Ajout d'un listener
Créez une classe ou un record qui représentera votre évènement `trainer:new`.
Cette classe contient l'adresse mail du trainer, ainsi que son nom.
Annotez cette classe avec l'annotation `@PulsarMessage(schemaType = SchemaType.JSON)` pour indiquer à Spring Boot que cet objet devra être sérialisé en JSON.
Implémentez une classe `NewTrainerEventPulsarAdapter`.
L'annotation `@PulsarListener` permet de marquer une méthode Java comme devant être appelée lorsqu'un message est disponible dans un topic Pulsar.
Ajoutez une méthode à cette classe, qui porte l'annotation, et reçoit en paramètre votre classe d'évènement :
[source,java]
----
@PulsarListener(topics = "trainer:new", subscriptionType = SubscriptionType.Shared)
void receiveEvent(NewTrainerEvent event) {
// TODO
}
----
Cette méthode écoute sur un topic `<votre-nom>:trainer:new`.
NOTE: On utilise un nommage de topic `trainer:new` avec votre nom en préfixe, pour éviter les conflits entre les étudiants !
Le paramètre `SubscriptionType.Shared` permet de partager la connexion au topic entre plusieurs instances de votre micro-service !
Cette méthode pourra appeler la méthode de service existant par ailleurs.
Le démarrage de votre application devrait afficher les logs de connexion au topic pulsar :
[source]
----
o.a.p.c.impl.ConsumerStatsRecorderImpl : Starting Pulsar consumer status recorder with config: {"topicNames":["persistent://public/default/new-trainer"],"topicsPattern":null,"subscriptionName":"org.springframework.Pulsar.PulsarListenerEndpointContainer#0","subscriptionType":"Shared","subscriptionProperties":null,"subscriptionMode":"Durable","receiverQueueSize":1000,"acknowledgementsGroupTimeMicros":100000,"maxAcknowledgmentGroupSize":1000,"negativeAckRedeliveryDelayMicros":60000000,"maxTotalReceiverQueueSizeAcrossPartitions":50000,"consumerName":null,"ackTimeoutMillis":0,"tickDurationMillis":1000,"priorityLevel":0,"maxPendingChunkedMessage":10,"autoAckOldestChunkedMessageOnQueueFull":false,"expireTimeOfIncompleteChunkedMessageMillis":60000,"cryptoFailureAction":"FAIL","properties":{},"readCompacted":false,"subscriptionInitialPosition":"Latest","patternAutoDiscoveryPeriod":60,"regexSubscriptionMode":"PersistentOnly","deadLetterPolicy":null,"retryEnable":false,"autoUpdatePartitions":true,"autoUpdatePartitionsIntervalSeconds":60,"replicateSubscriptionState":false,"resetIncludeHead":false,"batchIndexAckEnabled":false,"ackReceiptEnabled":false,"poolMessages":false,"startPaused":false,"autoScaledReceiverQueueSizeEnabled":false,"topicConfigurations":[],"maxPendingChuckedMessage":10}
o.a.p.c.impl.ConsumerStatsRecorderImpl : Pulsar client config: {"serviceUrl":"pulsar://localhost:6650","authPluginClassName":null,"authParams":null,"authParamMap":null,"operationTimeoutMs":30000,"lookupTimeoutMs":30000,"statsIntervalSeconds":60,"numIoThreads":22,"numListenerThreads":22,"connectionsPerBroker":1,"connectionMaxIdleSeconds":25,"useTcpNoDelay":true,"useTls":false,"tlsKeyFilePath":null,"tlsCertificateFilePath":null,"tlsTrustCertsFilePath":null,"tlsAllowInsecureConnection":false,"tlsHostnameVerificationEnable":false,"concurrentLookupRequest":5000,"maxLookupRequest":50000,"maxLookupRedirects":20,"maxNumberOfRejectedRequestPerConnection":50,"keepAliveIntervalSeconds":30,"connectionTimeoutMs":10000,"requestTimeoutMs":60000,"readTimeoutMs":60000,"autoCertRefreshSeconds":300,"initialBackoffIntervalNanos":100000000,"maxBackoffIntervalNanos":60000000000,"enableBusyWait":false,"listenerName":null,"useKeyStoreTls":false,"sslProvider":null,"tlsKeyStoreType":"JKS","tlsKeyStorePath":null,"tlsKeyStorePassword":null,"tlsTrustStoreType":"JKS","tlsTrustStorePath":null,"tlsTrustStorePassword":null,"tlsCiphers":[],"tlsProtocols":[],"memoryLimitBytes":67108864,"proxyServiceUrl":null,"proxyProtocol":null,"enableTransaction":false,"dnsLookupBindAddress":null,"dnsLookupBindPort":0,"dnsServerAddresses":[],"socks5ProxyAddress":null,"socks5ProxyUsername":null,"socks5ProxyPassword":null,"description":null,"openTelemetry":null}
o.a.pulsar.client.impl.ConsumerImpl : [persistent://public/default/trainer:new][org.springframework.Pulsar.PulsarListenerEndpointContainer#0] Subscribing to topic on cnx [id: 0x58864231, L:/127.0.0.1:38618 - R:localhost/127.0.0.1:6650], consumerId 0
o.a.pulsar.client.impl.ConsumerImpl : [persistent://public/default/trainer:new][org.springframework.Pulsar.PulsarListenerEndpointContainer#0] Subscribed to topic on localhost/127.0.0.1:6650 -- consumer: 0
----
Implémentez toutes les méthodes disponibles sur le mailing service avec des listener Pulsar :
* envoi d'un email de bienvenue (reçoit le nom d’un Trainer en paramètre, ainsi que son email)
* envoi d'un email de fin de combat (reçoit les noms des 2 adversaires, leurs emails, et l’information de qui a gagné le combat)
== `trainer-api`
=== Configuration
Ajoutez la dépendance `spring-boot-starter-pulsar` à votre projet `trainer-ui`.
Configurez les properties suivantes dans un fichier `application-local.properties`, pour utiliser votre instance locale :
[source,properties]
.application-local.properties
----
spring.pulsar.client.service-url=pulsar://localhost:6650
spring.pulsar.admin.service-url=http://localhost:6080
----
=== Ajout d'un producer
Spring propose un `PulsarTemplate` pour poster des messages dans un topic.
Dans une classe de `game-ui`, nommée `UserEventsPulsarAdapter`, utilisez le `PulsarTemplate` (reçu en injection de dépendance) pour envoyer les évènements à destination du `mailing-api` dans le topic consacré `<votre-nom>:trainer:new`.
À titre d'exemple, voici un usage du `PulsarTemplate` pour envoyer un message sur un topic :
[source,java]
----
pulsarTemplate.send(
"trainer:new",
new NewTrainerEvent("Ash", "ash@gitlab-classrooms.org")
);
----
TIP: N'hésitez pas à copier/coller votre classe correspondant à l'évènement attendu depuis `mailing-api`.
TIP: Isolez toutes ces classes dans un package consacré. Vous pouvez aussi exposer une interface `UserEventsPort` dans votre couche "domaine" si elle existe, pour reprendre les principes de l'architecture hexagonale.
== `battle-api`
Dans `battle-api`, implémentez l'envoi d'un message lors de la fin d'un combat, à destination du `mailing-api` dans le topic consacré `<votre-nom>:battle:end`, de la même manière que cela a été fait entre `game-ui` et `mailing-api`.
== Configuration pour Clever Cloud
La configuration de l'utilisation de Pulsar sur Clever Cloud nécessite quelques ajustements :
* l'instance de Pulsar est partagée entre tous les étudiants
* la connexion à Pulsar nécessite une authentification
* les topics peuvent être créés dans un tenant/namespace unique
Toutes les informations nécessaires à la connexion à Pulsar sont disponibles à 2 endroits :
* dans la console https://console.clever-cloud.com/organisations/orga_d02d9099-9664-47fd-8029-d90e36628e1d/addons/addon_baad03f5-7cbd-4d52-9b86-df292644b955/services-dependencies[Clever Cloud, role="external", window="_blank"].
* dans un secret sur https://vault-alom-2024.cleverapps.io/ui/vault/secrets/secret/kv/list[Vault, role="external", window="_blank"].
.Les secrets Pulsar dans Clever Cloud
image::images/clever-pulsar.png[]
.Les secrets Pulsar dans Vault
image::images/vault-pulsar.png[]
Configurez dans vos projets `mailing-api`, `game-ui` et `battle-api` l'utilisation de l'instance Pulsar de Clever Cloud :
[source,properties]
.application-clever.properties
----
spring.pulsar.client.service-url= #<1>
spring.pulsar.client.authentication.plugin-class-name=org.apache.pulsar.client.impl.auth.AuthenticationToken
spring.pulsar.client.authentication.param.token= #<2>
spring.pulsar.admin.service-url= #<3>
spring.pulsar.admin.authentication.plugin-class-name=org.apache.pulsar.client.impl.auth.AuthenticationToken
spring.pulsar.admin.authentication.param.token= #<2>
spring.pulsar.defaults.topic.tenant= #<4>
spring.pulsar.defaults.topic.namespace= #<5>
----
1. Utilisez la valeur de `ADDON_PULSAR_BINARY_URL`
2. Utilisez la valeur de `ADDON_PULSAR_TOKEN`
3. Utilisez la valeur de `ADDON_PULSAR_HTTP_URL`
4. Utilisez la valeur de `ADDON_PULSAR_TENANT`
5. Utilisez la valeur de `ADDON_PULSAR_NAMESPACE`
This diff is collapsed.
This diff is collapsed.
w11-eda/images/clever-pulsar.png

34.1 KiB

w11-eda/images/pokemon-archi.png

57.3 KiB

w11-eda/images/vault-pulsar.png

38.2 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment