Spring cloud: introduction to service discovery using netflix eureka
Tags: spring, java, eureka, cloud
Published: 2022-02-11 23:16:18

Micro-services are all good until they come with their distributed challenges which normally we don't face in monolithic based applications. Just like this one! 

## Understanding the problem

In order to fully get the main purpose of the solution let us first understand the underlying problem.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dtykjd163n264gromr38.png)

As the diagram above shows, we have to micro-services communicating via a certain network:
- Micro-service I with the IP address **10.10.10.10**, and port **8080**
- Micro-service II with the IP address **20.20.20.20**, and port **8090**

All working peacefully until the second micro-service changed its address and port for some reason.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/goalbpttrw926n56i3r0.png)

As result the micro-service I cannot communicate with micro-service II since it doesn't have the new address and port (30.30.30.30:5000).
To resolve this we need to provide **manually** the micro-service I with the micro-service II's new address and port. **What if we can do that automatically?**

The answer is YES, and that's exactly what Netflix Eureka does.

## Eureka under the hood

The first thing MS2 will do is to register to the naming registry server (Eureka server) providing mainly its IP, port and status (UP or DOWN). [A]

Before MS1 makes the call to MS2 [D], it will fetch the MS2 coordinates from the naming registry [B] which will allow the communication to happen even if MS2 changes its location a million times as long as its registers to the Eureka server. The server will respond with the required data. [C]

You should also understand that by fetching the naming registry or registering to it, the micro-service becomes its client (Eureka client).



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcolkbw8euex1ce28c4q.png)

## Let's talk code

For this tutorial I'll be using:

Spring Boot 2.6.2
```xml
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.2</version>
        <relativePath/> <!-- lookup parent from repository -->
</parent>
```

Java 8 && Spring cloud 2021.0.0 

```xml
<properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>2021.0.0</spring-cloud.version>
</properties>
```

and of course the dependency management for the spring cloud modules

```xml
<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>
```

### Eureka server configuration

The Eureka server require the Spring Cloud starter netflix eureka server dependency

```xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
```

Then, we need a set of properties as the following

```yml
# Setting a name for out app
spring:
  application:
    name: registry-server

# Simply telling Eureka server to NOT fetch or register to any server since it's not a client.
eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
```
Finally, we need to declare our app as a registry service using the `@EnableEurekaServer` annotation:

```
@SpringBootApplication
@EnableEurekaServer
public class RegistryEurekaServerApplication {

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

}
```

You can find a user interface generated by Eureka, for our case is on <a href="localhost:8099">localhost:8099<a>

<p align="center">
  <img src="https://elattar.me/images/spring/spring-cloud-eureka-dashboard.png">
</p>

### Eureka client configuration

The Eureka client require the Spring Cloud starter netflix eureka client dependency

```xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
```
Also for this one, we need a set of properties:

```yml
# Setting a name for out app
spring:
  application:
    name: registry-eureka-client

eureka:
  client:
    # To register to the eureka server
    registerWithEureka: true

    # To fetch the registry from the eureka server
    fetchRegistry: true

    # The location of the eureka server
    serviceUrl:
      defaultZone: http://localhost:8099/eureka/

  instance:
    # The instance hostname
    hostname: localhost
  
    # The instance unique id
    instanceId: ${eureka.instance.hostname}:${spring.application.name}

    # A bench of health information end-points provided by eureka
    statusPageUrl: http://${eureka.hostname}/
    healthCheckUrl: http://${eureka.hostname}/actuator/health
    secureHealthCheckUrl: http://${eureka.hostname}/actuator/health

```

Finally, we need to declare our app as a discovery client (Eureka client) using the `@EnableDiscoveryClient` annotation:

```java
@SpringBootApplication
@EnableDiscoveryClient
public class RegistryEurekaClientApplication {

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

Once, we start our client app, we will notice that it successfully registered to the running eureka server.

<p align="center">
  <img src="https://elattar.me/images/spring/spring-cloud-eureka-register-1.png">
</p>

And on the UI dashboard, you can see this:

<p align="center">
  <img src="https://elattar.me/images/spring/spring-cloud-eureka-register-2.png">
</p>

This may seem **incomplete**, actually it is, since we're not fetching the eureka server for registered service instances and exploit them. That's the main purpose of the next article when we will be doing so using a **reverse proxy** called **Netflix Zuul**.

More articles [Here](https://elattar.me/).