A Guide to Spring Cloud Netflix Eureka

Service Discovery is one of the key tenets of a microservice-based architecture. Trying to hand-configure each client or some form of convention can be difficult to do and can be brittle. Eureka is the Netflix Service Discovery Server and Client. The server can be configured and deployed to be highly available, with each server replicating state about the registered services to the others.

In this post, I will cover the common uses of the Spring Cloud Netflix Eureka. This post is based on Java 21, Spring Boot 3.5.3, and Spring Cloud 2025.0.0.

Eureka Server

1. Create Project and Add Dependencies

Using Gradle

$ mkdir spring-cloud-eureka-server && cd spring-cloud-eureka-server
$ gradle init --use-defaults \
--type java-application \
--package com.taogen.springcloud

app/build.gradle.kts

plugins {
java
id("org.springframework.boot") version "3.5.3"
// Use the Spring Dependency Management plugin to manage Spring Cloud dependencies.
id("io.spring.dependency-management") version "1.1.7"
}

extra["springCloudVersion"] = "2025.0.0"

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}

repositories {
mavenCentral()
}

dependencies {
implementation("org.springframework.cloud:spring-cloud-starter-netflix-eureka-server")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

dependencyManagement {
imports {
mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}")
}
}

tasks.withType<Test> {
useJUnitPlatform()
}

Using Maven

$ mvn -B archetype:generate \
-DgroupId=com.taogen.springcloud \
-DartifactId=spring-cloud-eureka-server \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.5

pom.xml

<?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.taogen.springcloud</groupId>
<artifactId>spring-cloud-eureka-server</artifactId>
<version>1.0-SNAPSHOT</version>

<name>spring-cloud-eureka-server</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>21</maven.compiler.release>
<java.version>21</java.version>
<spring-boot.version>3.5.3</spring-boot.version>
<spring-cloud.version>2025.0.0</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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.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>

Using Spring Initializr

Go to https://start.spring.io/

Project Metadata

  • Group: com.taogen.springcloud
  • Artifact: spring-cloud-eureka-server

Add dependencies

  • Eureka Server

2. Spring Configuration

application.yml

spring:
application:
name: eureka-server
freemarker:
template-loader-path: classpath:/templates/
prefer-file-system-access: false
server:
# Sets the listening port for the Eureka Server
port: 8761
eureka:
instance:
hostname: localhost
client:
# Tells the Config Server to not register with the Eureka service
registerWithEureka: false
# Tells the Config Server to not cache registry information locally
fetchRegistry: false
# the service URL
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
# Sets the initial time to wait before the server takes requests
waitTimeInMsWhenSyncEmpty: 5

3. Eureka Server Application

EurekaServerApplication.java

package com.taogen.springcloud;

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

/**
* @author taogen
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}

4. Start and Verification

Starting Spring Cloud Eureka Server

Running the main() method in the EurekaServerApplication to start Spring Cloud Eureka Server.

Verification

Visiting http://localhost:8761/ to see the dashboard web page of Eureka Server.

Eureka Client

1. Create Project and Add Dependencies

Using Gradle

$ mkdir spring-cloud-eureka-client && cd spring-cloud-eureka-client
$ gradle init --use-defaults \
--type java-application \
--package com.taogen.springcloud

app/build.gradle.kts

plugins {
java
id("org.springframework.boot") version "3.5.3"
// Use the Spring Dependency Management plugin to manage Spring Cloud dependencies.
id("io.spring.dependency-management") version "1.1.7"
}

extra["springCloudVersion"] = "2025.0.0"

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}

repositories {
mavenCentral()
}

dependencies {
implementation("org.springframework.cloud:spring-cloud-starter-netflix-eureka-client")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-actuator")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

dependencyManagement {
imports {
mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}")
}
}

tasks.withType<Test> {
useJUnitPlatform()
}

Using Maven

$ mvn -B archetype:generate \
-DgroupId=com.taogen.springcloud \
-DartifactId=spring-cloud-eureka-client \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.5

pom.xml

<?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.taogen.springcloud</groupId>
<artifactId>spring-cloud-eureka-client</artifactId>
<version>1.0-SNAPSHOT</version>

<name>spring-cloud-eureka-client</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>21</maven.compiler.release>
<java.version>21</java.version>
<spring-boot.version>3.5.3</spring-boot.version>
<spring-cloud.version>2025.0.0</spring-cloud.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.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>

Using Spring Initializr

Go to https://start.spring.io/

Project Metadata

  • Group: com.taogen.springcloud
  • Artifact: spring-cloud-eureka-client

Add dependencies

  • Eureka Discovery Client
  • Spring Web
  • Spring Boot Actuator

2. Spring Configuration

application.yml

spring:
application:
name: eureka-client
eureka:
instance:
preferIpAddress: true
instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
client:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://localhost:8761/eureka/
healthcheck:
enabled: true
server:
# configure the service use a random port number
port: 0
management:
endpoints:
web:
exposure:
include: health,info,beans

3. Config Client Application

EurekaClientApplication.java

package com.taogen.springcloud;  

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

4. Start and Verification

Starting Spring Cloud Eureka Client

Running the main() method in the EurekaClientApplication to start Spring Cloud Eureka Client.

Verification

Visiting the Eureka server dashboard page http://localhost:8761/ to see whether the Eureka client is registered in the Eureka server.

5. Using the EurekaClient

Once you have an application that is a discovery client, you can use it to discover service instances from the Eureka Server.

One way to do so is to use the native com.netflix.discovery.EurekaClient.

For example, Call the eureka-client-2 application’s /greeting endpoint from Eureka client 1:

@Autowired
private EurekaClient eurekaClient;

@GetMapping("/callEurekaClient2")
public String callEurekaClient2() {
InstanceInfo instance = eurekaClient.getNextServerFromEureka("EUREKA-CLIENT-2", false);
String homePageUrl = instance.getHomePageUrl();
System.out.println("Home Page URL: " + homePageUrl);
ResponseEntity<String> response = restTemplate.getForEntity(homePageUrl + "/greeting", String.class);
System.out.println(response.getBody());
return response.getBody();
}

Using Spring DiscoveryClient

@Autowired
private DiscoveryClient discoveryClient;

@GetMapping("/callEurekaClient2")
public String callEurekaClient2() {
String serviceId = "EUREKA-CLIENT-2";
String serviceUrl = discoveryClient.getInstances(serviceId).get(0).getUri().toString();
ResponseEntity<String> response = restTemplate.getForEntity(serviceUrl + "/greeting", String.class);
System.out.println(response.getBody());
return response.getBody();
}

Peer Awareness

Eureka can be made even more resilient and available by running multiple instances and asking them to register with each other.

Eureka Server

1. Set basic Eureka server configurations in application.yml

spring:
application:
name: eureka-server
freemarker:
template-loader-path: classpath:/templates/
prefer-file-system-access: false
eureka:
client:
# Tells the Config Server to not register with the Eureka service
registerWithEureka: false
# Tells the Config Server to not cache registry information locally
fetchRegistry: false
server:
# Sets the initial time to wait before the server takes requests
waitTimeInMsWhenSyncEmpty: 5

2. Eureka server peer configurations

application-peer1.yml

server:
port: 8763
eureka:
instance:
hostname: peer3
client:
serviceUrl:
defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/

application-peer2.yml

server:
port: 8762
eureka:
instance:
hostname: peer2
client:
serviceUrl:
defaultZone: http://peer1:8761/eureka/,http://peer3:8763/eureka/

application-peer3.yml

server:
port: 8763
eureka:
instance:
hostname: peer3
client:
serviceUrl:
defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/

3. Add hostname in /etc/hosts

127.0.0.1 peer1
127.0.0.1 peer2
127.0.0.1 peer3

4. Running Eureka server peers

Gradle

./gradlew bootRun --args='--spring.profiles.active=peer1'
./gradlew bootRun --args='--spring.profiles.active=peer2'
./gradlew bootRun --args='--spring.profiles.active=peer3'

Maven

mvn spring-boot:run -Dspring-boot.run.profiles=peer1
mvn spring-boot:run -Dspring-boot.run.profiles=peer2
mvn spring-boot:run -Dspring-boot.run.profiles=peer3

5. View Eureka server dashboards

Accessing each Eureka server dashboard, you can see that each Eureka server has two DS Replicas.

Eureka server dashboards’ URL:

Eureka Client

1. Register a Eureka client to the Eureka Server Cluster

Add all Eureka server peers to eureka.client.serviceUrl.defaultZone

eureka:
client:
serviceUrl:
defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/,http://peer3:8763/eureka/

The complete Eureka client configuration file application.yml:

spring:
application:
name: eureka-client
eureka:
instance:
preferIpAddress: true
instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
client:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/,http://peer3:8763/eureka/
healthcheck:
enabled: true
server:
# configure the service to use a random port number
port: 0
management:
endpoints:
web:
exposure:
include: health,info,beans

References

[1] Spring Microservices in Action, Second Edition

[2] Spring Cloud Netflix Documentation

[3] Eureka Server Cluster Setup Tutorial