Implémentation et test d'une partie de la pile Netflix OSS
Ce projet utilise docker-compose et des conteneurs disponible sur la page docker hub.
Avant l’installation, télécharger et installer Docker. Le projet a été concue sur la version 19.03.12 de Docker.
L’installation se fait via la commande
docker-compose up
:
Placer vous dans le répertoires amisno-docker-bootstrap :
amisno-docker-bootstrap
|__ …
|__ docker-compose.ymldocker-compose up Creating network "amisno-docker-bootstrap_default" with the default driver Creating amisno-docker-bootstrap_amisno-config-server_1 ... done Creating amisno-docker-bootstrap_mongo_1 ... done Creating amisno-docker-bootstrap_amisno-infra-eureka_1 ... done Creating amisno-docker-bootstrap_amisno-cloud-gateway_1 ... done Creating amisno-docker-bootstrap_amisno-catalog-service_1 ... done Creating amisno-docker-bootstrap_amisno-order-service_1 ... done Creating amisno-docker-bootstrap_amisno-catalog-service2_1 ... done
Si vous voulez modifiez un repo, il vous faudera recompiler la jar et re-créer une image Docker. Exemple :
> cd amisno-spring-gateway
amisno-spring-gateway > mvn clean install # Cette commande va créer un dossier target contenant la jar
amisno-spring-gateway > docker build -t <tagName> . # On créer ensuite l'image avec le tag <tagName>
amisno-spring-gateway > cd ../amisno-docker-bootstrap
amisno-docker-bootstrap > nano docker-compose.yml # Editer le fichier yml en mettant à jour le tag avec <tagName>
La liste des dépendances :
Spring Cloud Configuration permet de centraliser les fichiers de configurations utilisé par les microservices. Les fichiers de configuration sont stocké dans un répertoire git. Ils sont utilisés par les microservices au runtime.
Netflix Eureka est un annuaire qui fait le lien entre un service et une adresse IP. L’avantage d’Eureka est que les services n’ont pas tous besoin de connaitre l’IP de chacun à tout moment. L’information est centralisé sur le serveur Eureka. L’enrengistrement peut se faire via le SDK spring “Eureka-client” ou directement en attaquant l’API Rest.
Spring cloud gateway est le point d’entrée de l’application. Le gateway crée une table de routage à partir de l’annuaire Eureka.
Netflix Ribbon est un Load balancer coté client, c’est à dire que c’est à la charge de l’appelant de choisir le serveur à attaquer. Ribbon est configurable depuis le fichier de configuration de l’application (application.yml ou bootstrap.yml). Par exemple :
<clientName>.ribbon.NFLoadBalancerRuleClassName = com.netflix.loadbalancer.WeightedResponseTimeRule # où clientName represente le nom que l'on renseigne dans le décorateur @RibbonClient(name= "<clientName>")
Dans l’exemple ci dessus, la classe com.netflix.loadbalancer.WeightedResponseTimeRule est une classe mis à disposition par Ribbon pour faire du load balancing, celle ci est customisable en implémentatant l’interface IRule. Plus d’information ici.
La stratégie de load balancing par défaut et le Round-Robin
Resilience4j est une libraire de Fault Tolerance pour java8.
Il permet d’ajouter un comportement aux erreurs renvoyé par l’applicaiton.
Le module principale est le circuit breaker (représenté par son logo), qui simule le comportement d’un circuit électrique avec 3 état :
Dans le cadre d’un projet spring boot 2, il suffit d’jouter ces dépendances au fichier de builde (build.gradle dans un projet gradle) :
dependencies {
...
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-actuator'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-aop'
implementation "io.github.resilience4j:resilience4j-spring-boot2:${resilience4jVersion}"
implementation("io.github.resilience4j:resilience4j-reactor:${resilience4jVersion}")
implementation("io.github.resilience4j:resilience4j-all:${resilience4jVersion}") // Optional, only required when you want to use the Decorators class
/* To add a specific core-module
implementation "io.github.resilience4j:resilience4j-circuitbreaker:${resilience4jVersion}"
implementation "io.github.resilience4j:resilience4j-ratelimiter:${resilience4jVersion}"
implementation "io.github.resilience4j:resilience4j-retry:${resilience4jVersion}"
implementation "io.github.resilience4j:resilience4j-bulkhead:${resilience4jVersion}"
implementation "io.github.resilience4j:resilience4j-cache:${resilience4jVersion}"
implementation "io.github.resilience4j:resilience4j-timelimiter:${resilience4jVersion}"
/**/
}
A partir de là, il est possible de configurer les modules dans le fichier de configuration de l’application (application.yml) :
resilience4j.circuitbreaker:
configs:
default:
registerHealthIndicator: true
minimumNumberOfCalls: 3
permittedNumberOfCallsInHalfOpenState: 1
automaticTransitionFromOpenToHalfOpenEnabled: true
waitDurationInOpenState: 10s
failureRateThreshold: 20
eventConsumerBufferSize: 1
recordExceptions:
- org.springframework.web.client.HttpServerErrorException
- java.util.concurrent.TimeoutException
- java.io.IOException
instances:
productCatalog:
baseConfig: default
Enfin il faut décorer les fonctions souhaitées avec un module et les associer avec une instance :
@CircuitBreaker(name = productCatalog)
@Bulkhead(name = productCatalog)
@RateLimiter(name = productCatalog)
private Phone findOne(Long Id) {
...
}
Si vous trouvez un bug, veuillez nous contacter s’il vous plait. :)
Les auteurs d’AMiSNO sont FourmiPanda & Xabibax