Spring Cloud Service Discovery with Netflix Eureka

Learn to create microservice, based on Spring cloud, on Netflix Eureka registry server and how other microservices (Eureka clients) use it to register and discover services to call their APIs.

We will be using Spring Boot based Spring Cloud API. We will use Netflix Eureka server for building the service registry server and Eureka clients which will register themselves and discover other services to call REST APIs.

Overview

We will create three microservices for this Netflix Eureka example.

  1. Eureka Service Registry Server – This microservice will provide the service registry and discovery server.
  2. Student Microservice – Which will give some functionality based on Student entity. It will be a rest based service and most importantly it will be a eureka client service, which will talk with eureka service to register itself in the service registry.
  3. School Microservice – Same type as of Student service – only added feature is that it will invoke Student service with service look up mechanism. We will not use absolute URL of student service to interact with that service.

Here is the interaction diagram between above listed three services.

Component Interaction with each other

Tech Stack and Runtime

  • Java 1.8
  • Eclipse IDE
  • Spring cloud
  • Spring boot
  • Spring Rest
  • Maven
Table of Contents

What is Netflix Eureka Server and Clients?
Eureka Service Registry Server
Eureka Client - Student Service
Eureka Client - School Service
Demo of Service Discovery and Calling
Things to check if facing any error
Summary

What is Netflix Eureka Server and Clients?

As we know these days, there is a lot of momentum around Microservices. The transition from Monolithic to Microservice based architecture gives many benefits for future in terms of maintainability, scalability, high availability etc. However at the same time, there are many challenges also while doing this migration. One of them is to maintain individual Microservices addresses. This task can be hugely complex – depending on number of services and their dynamic nature. If whole infrastructure is distributed and there is some replication as well, then maintaining this service addresses becomes harder.

To solve this, in the distributed computing are there is a concept called ‘Service registration and discovery’ where one dedicated server is responsible to maintain the registry of all the Microservice that has been deployed and removed. This will act like a phone book of all other applications/microservices.

Think of it as a lookup service where microservices (clients) can register themselves and discover other registered microservices. When a client microservice registers with Eureka it provides metadata such as host, port, and health indicator thus allowing for other microservices to discover it. The discovery server expects a regular heartbeat message from each microservice instance. If an instance begins to consistently fail to send a heartbeat, the discovery server will remove the instance from his registry. This way we will have a very stable ecosystem of Microservices collaborating among each other, and on top of it we don’t have to manually maintain address of other Microservice, which is a next to impossible task if the scale up/down is very frequent, on demand and we use virtual host to host the services specially in the cloud environment.

Eureka Service Registry Server

Follow these steps to create and run Eureka server.

Create Eureka Server

Create a Spring boot project from Spring Boot initializer portal with two dependencies i.e. Eureka server and Actuator. Give other maven GAV coordinates and download the project.

Eureka Server Service Project Generation

Unzip and import the project into Eclipse as existing maven project. In this step, all necessary dependencies will be downloaded from maven repository.

Now open SpringEurekaServerApplication class that spring already has generated in the downloaded project and add the @EnableEurekaServerannotation on the class.

package com.example.howtodoinjava.springeurekaserver;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
 
@EnableEurekaServer
@SpringBootApplication
public class SpringEurekaServerApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(SpringEurekaServerApplication.class, args);
    }
}

Build the project once again. With this annotation, this artifact will act like microservice registry and discovery server.

Server Configuration

Create one file called application.yml in the src\main\resources directory. Add these properties –

server:
  port: ${PORT:8761} # Indicate the default PORT where this service will be started

eureka:
  client:
    registerWithEureka: false	#telling the server not to register himself in the service registry
    fetchRegistry: false
  server:
    waitTimeInMsWhenSyncEmpty: 0	#wait time for subsequent sync

Create another file called bootstrap.yml in the src\main\resources directory. Add these properties –

spring:
  application:
    name: eureka
  cloud:
    config:
      uri: ${CONFIG_SERVER_URL:http://localhost:8888}

Test Eureka Server

Start the application as spring boot application. Open browser and go to http://localhost:8761/, you should see the eureka server home page which looks like below.

Eureka Console Without Any Client

Please note that at this point no service is registered here which is expected and once we will spin up the client services, this server will automatically updated with the details of the client services.

Eureka Client – Student Service

Follow these steps to create and run Eureka client running student service.

Create Eureka Client Project

Create a Spring boot project from initializer portal with four dependencies i.e. Actuator, Web, Rest Repositories, Eureka Discovery. Give other maven GAV coordinates and download the project.

Client Project Generation –
Student Microservice

Unzip and import the project into Eclipse as existing maven project.

Now add the @EnableEurekaClient annotation on Spring boot application class present in src folder. With this annotation, this artifact will act like a spring discovery client and will register itself in the eureka server attached to this service.

package com.example.howtodoinjava.springeurekaclientstudentservice;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
 
@SpringBootApplication
@EnableEurekaClient
public class SpringEurekaClientStudentServiceApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(SpringEurekaClientStudentServiceApplication.class, args);
    }
}

Client Configuration

Create one file called application.yml in the src\main\resources directory and add below lines.

server:
  port: 8098	#default port where the service will be started

eureka:			#tells about the Eureka server details and its refresh time
  instance:
    leaseRenewalIntervalInSeconds: 1
    leaseExpirationDurationInSeconds: 2
  client:
    serviceUrl:
      defaultZone: http://127.0.0.1:8761/eureka/
    healthcheck:
      enabled: true
    lease:
      duration: 5

spring:		
  application:
    name: student-service 	#current service name to be used by the eureka server
    
management:
  security:
    enabled: false	#disable the spring security on the management endpoints like /env, /refresh etc. 

logging:
  level:
    com.example.howtodoinjava: DEBUG

Add REST API

Now add one RestController and expose one rest endpoint for getting all the student details for a particular school. Here we are exposing /getStudentDetailsForSchool/{schoolname} endpoint to serve the business purpose. For simplicity, we are hard coding the student details.

package com.example.howtodoinjava.springeurekaclientstudentservice.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.example.howtodoinjava.springeurekaclientstudentservice.domain.Student;

@RestController
public class StudentServiceController {

	private static Map<String, List<Student>> schooDB = new HashMap<String, List<Student>>();

	static {
		schooDB = new HashMap<String, List<Student>>();

		List<Student> lst = new ArrayList<Student>();
		Student std = new Student("Sajal", "Class IV");
		lst.add(std);
		std = new Student("Lokesh", "Class V");
		lst.add(std);

		schooDB.put("abcschool", lst);

		lst = new ArrayList<Student>();
		std = new Student("Kajal", "Class III");
		lst.add(std);
		std = new Student("Sukesh", "Class VI");
		lst.add(std);

		schooDB.put("xyzschool", lst);

	}

	@RequestMapping(value = "/getStudentDetailsForSchool/{schoolname}", method = RequestMethod.GET)
	public List<Student> getStudents(@PathVariable String schoolname) {
		System.out.println("Getting Student details for " + schoolname);

		List<Student> studentList = schooDB.get(schoolname);
		if (studentList == null) {
			studentList = new ArrayList<Student>();
			Student std = new Student("Not Found", "N/A");
			studentList.add(std);
		}
		return studentList;
	}
}

Student class is a simple POJO.

public class Student 
{
	private String name;
	private String className;
	
	public Student(String name, String className) {
		super();
		this.name = name;
		this.className = className;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}
}

Test Eureka Client

Start this project as spring boot application. Now verify that this service has been registered in Eureka server automatically. Go to Eureka service console and refresh the page. Now if everything goes well, we will see one entry for student-service in the eureka service console. This indicates that both Eureka server and client are aware each other.

Eureka console with Student service registered

We will now verify that the /getStudentDetailsForSchool/{schoolname} endpoint is up and running. Go to browser and go to http://localhost:8098/getStudentDetailsForSchool/abcschool, it will give the Student details for a particular school abcschool.

Student Service response

Eureka Client – School Service

Now we will create school service which will register itself with eureka server – and it will discover and invoke student-service without hardcoded URL path.

Follow exact steps for creating student service, to create and run Eureka client running school service as well.

Create Eureka Client Project

Create a Spring boot project from initializer portal with four dependencies i.e. Actuator, Web, Rest Repositories, Eureka Discovery. Give other maven GAV coordinates and download the project.

Unzip and import the project into Eclipse as existing maven project.

Now add the @EnableEurekaClient annotation on Spring boot application class present in src folder. With this annotation, this artifact will act like a spring discovery client and will register itself in the eureka server attached to this service.


package com.example.howtodoinjava.springeurekaclientschoolservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
public class SpringEurekaClientSchoolServiceApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringEurekaClientSchoolServiceApplication.class, args);
	}
}

Client Configuration

Create one file called application.yml in the src\main\resources directory and add below lines. These configurations are very similar to student service except port number and service name.

server:
  port: 9098	#port number

eureka:
  instance:
    leaseRenewalIntervalInSeconds: 1
    leaseExpirationDurationInSeconds: 2
  client:
    serviceUrl:
      defaultZone: http://127.0.0.1:8761/eureka/
    healthcheck:
      enabled: true
    lease:
      duration: 5

spring:
  application:
    name: school-service 	#service name

logging:
  level:
    com.example.howtodoinjava: DEBUG

Add REST API which consume student service’s REST API

Now add one RestController and expose one rest endpoint for getting school details. This endpoint will use the service discovery style URL using the application name, instead full URL with host:port.

package com.example.howtodoinjava.springeurekaclientschoolservice.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class SchoolServiceController {
	@Autowired
	RestTemplate restTemplate;

	@RequestMapping(value = "/getSchoolDetails/{schoolname}", method = RequestMethod.GET)
	public String getStudents(@PathVariable String schoolname) 
	{
		System.out.println("Getting School details for " + schoolname);

		String response = restTemplate.exchange("http://student-service/getStudentDetailsForSchool/{schoolname}",
								HttpMethod.GET, null, new ParameterizedTypeReference<String>() {}, schoolname).getBody();

		System.out.println("Response Received as " + response);

		return "School Name -  " + schoolname + " \n Student Details " + response;
	}

	@Bean
	@LoadBalanced
	public RestTemplate restTemplate() {
		return new RestTemplate();
	}
}

This way we can get rid of specific service configuration and we can give the service look up responsibility to eureka server and rest template provided here. We can also apply load balancing (see @LoadBalanced annotation) here if the multiple instances are running for the same service.

The URL we have used is http://student-service/getStudentDetailsForSchool/{schoolname}. Clearly we are using only service name student-service in the place of host:port. This will be handled internally by spring framework, eureka server and rest template together.

Demo of Service Discovery and Calling

Now start the school service as well. All three services are started. Check the eureka server console. Bothe student and school services must be registered there.

Eureka console with both services registered

Go to browser and go to http://localhost:9098//getSchoolDetails/abcschool, it will give the school details for a particular school abcschool details. We have invoked student service internally. The response will look like in the browser:

School Service Response

Things to check if facing any error

  1. Annotations @EnableEurekaServer and @EnableEurekaClient are the heart of the application ecosystem. Without those two things will not work at all.
  2. Make sure at the time of starting the config client service, eureka server service is running already, otherwise it might take some time to register, which might create confusion while testing.

Summary

We saw how easily one can deploy service registry and discovery server as well as clients efficiently. Spring framework is maintaining lots of things internally. Here we are just using couple of annotations and very minimal configuration to achieve the whole things quickly.

That’s all about creating spring could eureka server and service registration for microservices. Please add comments if you have any difficulty executing this article. We will be happy to look into the problem.

Happy Learning !!

Leave a Reply

28 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions, and frequently asked interview questions.