In this previous couple of tutorials, we have seen:
Spring Boot Microservices Communication Example using RestTemplate
Spring Boot Microservices Communication Example using WebClient
Spring Boot Microservices Communication Example using Spring Cloud Open Feign
In this tutorial, we will learn how to create a Service Registry using Spring Cloud Netflix Eureka in the Spring boot microservices project.
Service Registry and Discovery Overview
In the microservices projects, Service Registry and Discovery play an important role because we most likely run multiple instances of services and we need a mechanism to call other services without hardcoding their hostnames or port numbers. In addition to that, in Cloud environments service instances may come up and go down anytime. So we need some automatic service registration and discovery mechanism.What we will build?
We can use Netflix Eureka Server to create a Service Registry and make our microservices (department-service and user-service) as Eureka Clients so that as soon as we start a microservice it will get registered with Eureka Server automatically with a logical Service ID. Then, the other microservices, which are also Eureka Clients, can use Service ID to invoke REST endpoints.Spring Cloud makes it very easy to create a Service Registry and discover other services using Load Balanced RestTemplate:
@Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); }
Prerequisites
1. Create and Setup Spring boot project in IntelliJ IDEA
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
Let's create a Spring boot project using the spring initializr.
Refer to the below screenshot to enter details while creating the spring boot application using the spring initializr:
<?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.7.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>net.javaguide</groupId>
<artifactId>service-registry</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>service-registry</name>
<description>service-registry</description>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2021.0.4</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</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>${spring-cloud.version}</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>
2. Add @EnableEurekaServer annotation
We need to add @EnableEurekaServer annotation to make our SpringBoot application a Eureka Server-based Service Registry.
package net.javaguides.serviceregistry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class ServiceRegistryApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRegistryApplication.class, args);
}
}
3. Disable Eureka Server as Eureka Client
By default, each Eureka Server is also a Eureka client and needs at least one service URL to locate a peer. As we are going to have a single Eureka Server node (Standalone Mode), we are going to disable this client-side behavior by configuring the following properties in the application.properties file.
spring.application.name=service-registry
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
4. Launch Eureka Server (Demo)
Netflix Eureka Service provides UI where we can see all the details about registered services.
Now run ServiceRegistryApplication and access http://localhost:8761 which will display the UI similar to the below screenshot.
5. Registering Department-Service Microservice as Eureka Client
Let us make this department-service as a Eureka Client and register with the Eureka Server.
Add the Eureka Discovery starter to department-service:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
Also, add the Spring cloud dependencies:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Add version as property:
<properties>
<java.version>17</java.version>
<spring-cloud.version>2021.0.4</spring-cloud.version>
</properties
With spring-cloud-starter-netflix-eureka-client on the classpath, we just need to configure eureka.client.service-url.defaultZone property in application.properties to automatically register with the Eureka Server.
spring.application.name=DEPARTMENT-SERVICE
eureka.instance.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
When a service is registered with Eureka Server it keeps sending heartbeats for certain intervals. If the Eureka server didn’t receive a heartbeat from any service instance it will assume the service instance is down and take it out from the pool.
6. Run department-service Eureka Client (Demo)
With this configuration in place, start department-service and visit http://localhost:8761.
You should see that department-service is registered with SERVICE ID as DEPARTMENT-SERVICE. You can also notice the status as UP(1) which means the services are up and running and one instance of department-service is running.
7. Registering User-Service Microservice as Eureka Client
Let us make this user-service as a Eureka Client and register with the Eureka Server.
Add the Eureka Discovery starter to user-service:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
Also, add the Spring cloud dependencies:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Add version as property:
<properties>
<java.version>17</java.version>
<spring-cloud.version>2021.0.4</spring-cloud.version>
</properties
With spring-cloud-starter-netflix-eureka-client on the classpath, we just need to configure eureka.client.service-url.defaultZone property in application.properties to automatically register with the Eureka Server.
spring.application.name=USER-SERVICE
eureka.instance.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
8. Run user-service Eureka Client (Demo)
With this configuration in place, start user-service and visit http://localhost:8761. You should see user-service is registered with SERVICE ID as USER-SERVICE.
You can also notice the status as UP(1) which means the services are up and running and one instance of user-service is running.
Multiple Instances of Department-Service
Let us start another instance of department-service on a different port using the following command.
java -jar -Dserver.port=8082 department-service-0.0.1-SNAPSHOT.jar
Suppose we want to invoke the department-service REST endpoint from the user-service. We can use RestTemplate to invoke the REST endpoint but there are 2 instances running.
We can register RestTemplate as a Spring bean with @LoadBalanced annotation:
@Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); }
The RestTemplate with @LoadBalanced annotation will internally use Ribbon LoadBalancer to resolve the ServiceID and invoke the REST endpoint using one of the available servers.
Change the URL in UserServiceImpl class:
ResponseEntity<DepartmentDto> responseEntity = restTemplate
.getForEntity("http://DEPARTMENT-SERVICE/api/departments/" + user.getDepartmentId(),
DepartmentDto.class);
With this kind of automatic Service Registration and Discovery mechanism, we no need to worry about how many instances are running and what are their hostnames and ports, etc
Conclusion
Related Tutorials
✅ Spring Boot Microservices Communication Example using RestTemplate
✅ Spring Boot Microservices Communication Example using WebClient
✅ Spring Boot Microservices Communication Example using Spring Cloud Open Feign
✅ Spring Boot Microservices - Spring Cloud Config Server
✅ Spring Boot Microservices - Spring Cloud Netflix Eureka-based Service Registry
Comments
Post a Comment
Leave Comment