Spring Cloud Consul Service and Discovery
In this tutorial we will be implementing a Spring Cloud Consul using Spring Cloud.Consul is one of the products of HashiCorp. Spring consul provides an easy way by which one can register instances as consul agent and that instances can be further discovered by clients using spring beans. There are sveral features provided by consul. Some of them includes configuration management with the use of Key/Value store , health checking etc. are provided by the consul.
Let us understand by a sceanerio of a system without the consul and a system using consul.
We can clearly see that with the help of consul, a centralised configuration can be done. Multiple environment support is provided by the consul.Consul also provides the benifit of instance update.
Firstly we need to download the consul agent. Now we need to find the ip address of our system.
Now run the following command in command prompt.
Now run the following url
http://localhost:8500/ui/dc1/services
You would see the consul running. Now we create the spring boot project and register their instance in the consul.
we will create two services and register their instances in consul.
-
Info
This will be the standard directory layout for maven project structure-
We need to start by creating a Maven pom.xml(Project Object Model) file. The pom.xml file contains the project configuration details.<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.javatechie</groupId> <artifactId>info-service</artifactId> <version>0.0.1-SNAPSHOT</version> <name>info-service</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
The application.properties file is as follows- Here we define the name for which the service will be registered in the consul.spring.application.name=Info-service server.port=8889
The main class can be defined as follows-package com.codeusingjava; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @RestController public class DemoApplication { @GetMapping("/test") public String getApp() { return "Finally you have achieved your goal"; } public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
InfoReceiver
The project structure for the service is as follows-
The standard pom.xml file can be defined as follows:-<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.codeusingjava</groupId> <artifactId>inforeceiver</artifactId> <version>0.0.1-SNAPSHOT</version> <name>user-service</name> <description>Spring cloud consul</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
The application.properties file for the service camn be defined as follows-spring.application.name=info-receiver server.port=8890
EnableDiscoveryClient annotation is implemented when working on consul. We can use this annotation with any of the DiscoveryClient.package com.codeusingjava.consul; import java.net.URI; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.context.annotation.Bean; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @SpringBootApplication @EnableDiscoveryClient @RestController public class InfoReceiverApplication { @Autowired private RestTemplate template; @Autowired private DiscoveryClient client; @GetMapping("/getInfo") public String invokeGreetingService() { URI geturi = client.getInstances("Info-service").stream().map(si -> si.getUri()).findFirst() .map(s -> s.resolve("/test")).get(); return template.getForObject(geturi, String.class); } public static void main(String[] args) { SpringApplication.run(InfoReceiverApplication.class, args); } @Bean public RestTemplate template() { return new RestTemplate(); } }
Run the application
Firstly run Info-service as spring boot application.Now run the info-receiver as spring boot application.
Refresh the above url. Both the instances of the service will be registered.
Now run the following url and see the output. The output will be displayed only when both the instances are successfully registered.
The consul output is as follows: