Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Microservice: Spring Cloud Eureka Server Configuration

DZone's Guide to

Microservice: Spring Cloud Eureka Server Configuration

Learn what a Eureka server does, why it is useful in microservice architecture, and how to complete its standalone setup.

· Integration Zone
Free Resource

Modernize your application architectures with microservices and APIs with best practices from this free virtual summit series. Brought to you in partnership with CA Technologies.

In the previous microservices articles, we learn how to configure and access a config server. In this tutorial, we learn what the Eureka server is. Why is it needed? What about Eureka server/client communication? How do we configure the Eureka server using Spring Cloud?

What Is the Eureka Server?

The Eureka server is nothing but a service discovery pattern implementation, where every microservice is registered and a client microservice looks up the Eureka server to get a dependent microservice to get the job done.

The Eureka Server is a Netflix OSS product, and Spring Cloud offers a declarative way to register and invoke services by Java annotation.

Why Is the Eureka Server?

To understand why the Eureka server is needed in microservice architecture, let's understand how one service calls another service REST endpoint for communication.

Say we need to call the employee payroll service to get payroll information for an employee. The payroll service is deployed on the localhost 8080 port (we got that information by passing the employee primary key) so we just call the following:

http://localhost:8080/payroll/1 or http://127.0.0.1/payroll/1

Where localhost/127.0.0.1 is the hostname/IP address and payroll is the payroll service context, 1 is the employee primary key.

But this is only possible when you know the hostname/IP addresses beforehand, then you can configure your URL. So here the hostname or IP address is a constraint or a pain point.

If the IP address of a server/container is fixed, then you can use that approach, but what happens when your IP addresses and hostname are unpredictable?

Nowadays, on a cloud platform, it is obvious that all the servers or containers use dynamic IPs for autoscaling. And the interesting thing is that in microservice architecture, the key principle is that your service can autoscaled as per load, so cloud platforms are ideal for microservices.

What I am trying to say here is that we can not predict the IP addresses of the container/server beforehand, so putting dependent services IP addresses in the config file is not a solution. We need a more sophisticated technique to identify the service, and Eureka server steps in here.

Eureka Server/Client Communication

Every microservice registers itself in the Eureka server when bootstrapped, generally using the {ServiceId} it registers into the Eureka server, or it can use the hostname or any public IP (if those are fixed). After registering, every 30 seconds, it pings the Eureka server to notify it that the service itself is available. If the Eureka server not getting any pings from a service for a quite long time, this service is unregistered from the Eureka server automatically and the Eureka server notifies the new state of the registry to all other services. I will write this mechanism elaborately in the next article.

Now one question may pop up our mind: what is the Eureka server itself?

The Eureka server is nothing but another microservice which treats itself as a Eureka client.

What I mean is that the Eureka server has to be highly available as every service communicates it to discover other services. So it is recommended that it should not be a single point of failure. To overcome it, we need multiple Eureka server instances running behind a load balancer. Now when there are multiple Eureka servers, each server needs to have synchronized registry details so that every server knows about the current state of every microservice registered in the Eureka server registry.

The Eureka server communicates its peer server as a client and clones the updated state of the registry, so the Eureka server itself acts as a client. We can perform this by just configuring the eureka.client.serviceUrl.defaultZone property.

The Eureka server works in two modes:

  • Standalone: in local, we configure a stand-alone mode where we have only one Eureka server (localhost) and the same cloning property from itself.

  • Clustered: we have multiple Eureka servers, each cloning its states from its peer.

The Eureka server can have a properties file and communicate with a config server as other microservices do.

Standalone Setup of Eureka Server

Step 1: Create a project template from https://start.spring.io/. While creating the template choose the following modules:

  1. Config Client
  2. Actuator
  3. Eureka Server

microservices

Step 2: Open the downloaded code template and import it as a Maven project in your IDE. The pom.xml looks like this:

<?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>

    <groupId>com.example</groupId>
    <artifactId>EmployeeEurekaServer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>EmployeeEurekaServer</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-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>

Step 3: Now open EmployeeEurekaServerApplication.java and put the annotation @EnableEurekaServer on top of the class. By doing so, this application now acts as a service registry. All other Microservices can register themselves by using this service URL (we will discuss this in the next article).

package com.example.EmployeeEurekaServer;

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

@EnableEurekaServer
@SpringBootApplication
public class EmployeeEurekaServerApplication {

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

Step 4: Now change the application.properties to bootstrap.properties as it may consult with the config server if it has any properties defined in config server. In the bootstrap.properties file, write the following lines:

spring.application.name=EmployeeEurekaServer
eureka.client.serviceUrl.defaultZone:http://localhost:9091/eureka/
server.port=9091
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
Name Description
spring.application.name Unique name for a Eureka server service.
eureka.client.serviceUrl.defaultZone It consults with other Eureka servers to sync the service registry. As it is in standalone mode, I am giving the local server address.
server.port In which port the server will be bound.
eureka.client.register-with-eureka This determines if this server registers itself as a client; as I said earlier, the Eureka server is also acting as a client so that it can sync the registry. The value being false means it prevents itself from acting as a client.
eureka.client.fetch-registry Does not register itself in the service registry.


Now our Eureka server setup is complete. We will now run this project as a Java application. Now hit the following URL: http://localhost:9091. You will see the following dashboard:

The Integration Zone is proudly sponsored by CA Technologies. Learn from expert microservices and API presentations at the Modernizing Application Architectures Virtual Summit Series.

Topics:
spring cloud ,microservices architecture ,eureka server ,microservices ,cloud

Published at DZone with permission of Shamik Mitra, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}