11 mars 2015

Netflix Eureka - Registre des services


Spring Cloud a pour objectif de fournir les serveurs et libraires prêts à l'emploi pour permettre les mécanismes suivants dans un cloud de serveurs :
  • Configuration distribuée et versionnée
  • Enregistrement et de découverte de services
  • Routing
  • Appels entre services
  • Load balancing
  • Coupe circuits
  • Vérouillage global
  • Election d'un leader
  • Etat d'un cluster
  • Distribution de messages entre services
Spring Cloud se décompose en plusieurs modules:
  • Spring Cloud Connectors:
    • Simplification de l'accès aux services du Cloud depuis les applications
    • Support de Cloud Foundry et de Heroku
    • Permet le support d'un cloud personnalisé
  • Spring Cloud Config:
    • Externalisation de la configuration dans un environnement distribué
    • Le serveur Spring Cloud Config Server centralise la configuration des applications sur les différents environnement
  • Spring Cloud Bus:
    • Serveur RabbitMQ : bus de messages basés sur le protocol AMQP pour la communication point-to-point et publish-subscribe

Pour faciliter la mise en place des serveurs et applications du cloud, il est préférable d'utiliser Spring Boot car il s'intègre très facilement à Spring Cloud via une simple dépendance Maven:
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter</artifactId>
    </dependency>

Spring Boot permet la mise en place rapide de serveurs et de services car il s'appuie sur le concept suivant :
  • Convention over configuration : nous n'avons plus besoin de tout configurer, Spring Boot utilise la configuration standard. Il est alors possible de surcharger la configuration par défaut via un fichier de configuration YAML

Code source de l'exemple

Pour la mise en oeuvre, le code source est disponible sur le repo Github:

Serveur Eureka

Eureka est un serveur de registre et de découverte de services.

Nous utilisons Spring Boot pour la mise en place d'un serveur Eureka.

Le fichier pom.xml contient la dépendance: La classe principale Application.java contient les annotations @EnableEurekaServer et @EnableDiscoveryClient : Le fichier de configuration application.yml contient le paramétrage du serveur et de Eureka : Démarrer le serveur Eureka à l'aide de :
mvn spring-boot:run
Aller sur la page : http://localhost:8761

Client Eureka

Nous allons tester l'enregistrement de deux applications "front" et "back" auprès du serveur Eureka.

Les deux applications contiennent le fichier pom.xml suivant (à part l'artifactId qui est différent): , avec la dépendance vers :
<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>

Les classes principales Application.java dispose de l'annotation @EnableEurekaClient qui indique que les deux applications seront enregistrées sur le serveur Eureka:
Pour l'application "front", nous indiquons dans le fichier application.yml le nom "front" pour identifier ensuite cette application dans Eureka, ainsi que le port du serveur Tomcat de cette application. De même pour l'application "back", mais avec comme nom "back"des deux applications "front": et "back": Démarrer les deux serveurs en lançant pour chacune la commande :
mvn spring-boot:run

Une fois les deux serveurs lancés, dans la log du serveur, nous voyons que les applications s'enregistrent auprès de Eureka:
pour l'application "back" :
DiscoveryClient_BOOTSTRAP/MacBook-Pro-de-Ludovic.local - Re-registering apps/BACK
DiscoveryClient_BOOTSTRAP/MacBook-Pro-de-Ludovic.local: registering service...
DiscoveryClient_BOOTSTRAP/MacBook-Pro-de-Ludovic.local - registration status: 204
DiscoveryClient_BOOTSTRAP/MacBook-Pro-de-Ludovic.local - retransmit instance info with status UP
DiscoveryClient_BOOTSTRAP/MacBook-Pro-de-Ludovic.local: registering service...
DiscoveryClient_BOOTSTRAP/MacBook-Pro-de-Ludovic.local - registration status: 204
et pour l'application "front" :
DiscoveryClient_BOOTSTRAP/MacBook-Pro-de-Ludovic.local - Re-registering apps/FRONT
DiscoveryClient_BOOTSTRAP/MacBook-Pro-de-Ludovic.local: registering service...
DiscoveryClient_BOOTSTRAP/MacBook-Pro-de-Ludovic.local - registration status: 204
DiscoveryClient_BOOTSTRAP/MacBook-Pro-de-Ludovic.local - retransmit instance info with status UP
DiscoveryClient_BOOTSTRAP/MacBook-Pro-de-Ludovic.local: registering service...
DiscoveryClient_BOOTSTRAP/MacBook-Pro-de-Ludovic.local - registration status: 204

la page du serveur Eureka http://localhost:8761/ affiche le statut de ces deux applications "front" et "back" que nous venons de démarrer:

Demander à Eureka l'URL d'une application

Dans l'application "front", nous allons nous servir du serveur Eureka pour récupérer l'URL de l'application "back" à partir de son identifiant enregistré dans le serveur Eureka.

Nous ajoutons le controlleur suivant dans l'application "front": La classe DiscoverClient permet de récupérer les informations d'un service à l'aide de la méthode getNextServerFromEureka et de l'identifiant de ce service, qui dans notre exemple est "BACK" pour l'application "back".

Le controlleur retourne maintenant l'URL de l'application "back" :

Cependant, il est préférable de ne pas utiliser directement la classe DiscoverClient de Netflix mais d'utiliser un wrapper.

Par exemple, la classe RestTemplate peut utiliser ce mécanisme en interne: on lui indique une liste de noms de serveurs et c'est elle qui demande au serveur Eureka l'adresse physique de l'application ou serveur cible.

Conclusion

Nous n'avons plus à utiliser directement les adresses physiques des applications et des serveurs. Ce sont eux qui s'enregistrent auprès de Eureka. Ensuite le service client demande à Eureka l'adresse physique du service à qui il souhaite s'adresser.

Ceci apporte plus de souplesse dans le paramétrage des environnements et des applications.