Introduction to Spring Cloud Netflix - Eureka
In the era of microservices, service discovery is a critical infrastructure component. As applications decompose into hundreds of independent services, hardcoding URLs or maintaining static lists of service locations becomes unmanageable. Microservices need a dynamic way to:
- Register their presence with a central registry.
- Discover other services without manual configuration.
- Handle failures and scaling gracefully.
Spring Cloud Netflix Eureka (often简称 Eureka) solves this problem by providing a client-side service discovery framework. Built by Netflix and integrated into the Spring Cloud ecosystem, Eureka simplifies service registration, discovery, and load balancing for Spring Boot applications.
This blog will teach you everything you need to know about Eureka—from core concepts to advanced features, best practices, and real-world examples. By the end, you’ll be able to build a production-ready service discovery layer for your microservices.
Table of Contents#
- What is Spring Cloud Netflix Eureka?
- Core Concepts
- Eureka Server
- Eureka Client
- Instance Registration
- Heartbeats (Lease Renewal)
- Service Discovery
- Caching
- Setting Up a Eureka Server
- Setting Up a Eureka Client
- Advanced Features
- High Availability (HA) Clusters
- Zone Affinity
- Custom Metadata
- Health Checks (with Spring Boot Actuator)
- Securing Eureka
- Best Practices
- Common Issues & Troubleshooting
- Example Use Case: Microservices with Eureka
- Conclusion
- References
1. What is Spring Cloud Netflix Eureka?#
Eureka is a REST-based service discovery server that enables microservices to:
- Register their network location (IP, port, metadata) with a central registry.
- Discover other services by querying the registry.
- Health Check instances to remove unhealthy services from the registry.
Eureka follows a client-server model:
- Eureka Server: The central registry that stores service instance information.
- Eureka Client: A library embedded in microservices to interact with the server (register, discover, send heartbeats).
Key advantages of Eureka:
- Decentralized: Clients cache registry data to reduce server load.
- Highly Available: Supports clustering to avoid single points of failure.
- Spring Boot-friendly: Auto-configured with minimal code.
2. Core Concepts#
Let’s break down Eureka’s core components and workflows.
2.1 Eureka Server#
The Eureka Server acts as the service registry. It:
- Stores metadata about service instances (IP, port, health status, custom attributes).
- Exposes a REST API for clients to register, deregister, and query instances.
- Provides a web dashboard (http://localhost:8761 by default) to visualize registered services.
By default, the Eureka Server runs on port 8761 and uses an in-memory datastore (no external database required).
2.2 Eureka Client#
Every microservice that needs to register or discover services is a Eureka Client. The client:
- Registers: On startup, sends a POST request to the Eureka Server with its metadata (e.g.,
spring.application.name, IP, port). - Renews: Sends periodic heartbeats (default: every 30 seconds) to the server to confirm it’s still alive.
- Fetches: Pulls the latest registry data from the server (default: every 30 seconds) and caches it locally.
- Deregisters: Sends a DELETE request to the server on shutdown to remove itself from the registry.
2.3 Instance Registration#
When a Eureka Client starts:
- It resolves the Eureka Server URL(s) from configuration.
- It sends a
RegisterInstancerequest with metadata like:- Service name (
spring.application.name). - IP address/hostname.
- Port.
- Health status.
- Custom metadata (e.g., version, environment).
- Service name (
- The Eureka Server adds the instance to its registry.
2.4 Heartbeats (Lease Renewal)#
To stay registered, the client sends heartbeats (HTTP PUT requests) to the server at regular intervals (default: 30 seconds). This is called a lease renewal.
If the server doesn’t receive a heartbeat for a configured period (default: 90 seconds), it marks the instance as unhealthy and evicts it from the registry (after an additional 60 seconds by default).
2.5 Service Discovery#
When a client needs to call another service (e.g., order-service calling user-service):
- The client queries its local cache for instances of
user-service. - If the cache is stale, it fetches the latest registry from the Eureka Server.
- The client uses a load balancer (e.g., Ribbon, included with Spring Cloud Netflix) to select an instance from the list.
- The client sends a request to the selected instance.
2.6 Caching#
Eureka Clients cache registry data locally to:
- Reduce load on the Eureka Server.
- Enable discovery even if the server is temporarily unavailable.
The cache is refreshed periodically (default: 30 seconds), so there may be a short delay before clients see new/removed instances.
3. Setting Up a Eureka Server#
Let’s build a Eureka Server from scratch using Spring Boot.
3.1 Step 1: Create a Spring Boot Project#
Use Spring Initializr to generate a project with these dependencies:
- Spring Cloud Eureka Server: Enables Eureka Server functionality.
- Spring Web: Required for the Eureka dashboard.
3.2 Step 2: Enable Eureka Server#
Add the @EnableEurekaServer annotation to your main application class:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}3.3 Step 3: Configure the Server#
Create an application.yml file with the following settings:
server:
port: 8761 # Default Eureka port
spring:
application:
name: eureka-server # Name of the Eureka Server itself
eureka:
client:
register-with-eureka: false # Don't register the server with itself (single-node setup)
fetch-registry: false # Don't fetch registry data (server doesn't need to discover services)
server:
enable-self-preservation: true # Prevent evicting healthy instances during network partitions3.4 Step 4: Run the Server#
Start the application and navigate to http://localhost:8761. You’ll see the Eureka dashboard with no services registered (yet!).
4. Setting Up a Eureka Client#
Now let’s build a microservice (user-service) that registers with the Eureka Server.
4.1 Step 1: Create a Spring Boot Project#
Use Spring Initializr with these dependencies:
- Spring Cloud Eureka Client: Enables Eureka Client functionality.
- Spring Web: Exposes REST endpoints.
- Spring Boot Actuator: For health checks (optional but recommended).
4.2 Step 2: Enable Discovery Client#
Add the @EnableDiscoveryClient annotation to your main class (this tells Spring to register the service with Eureka):
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}4.3 Step 3: Configure the Client#
Create an application.yml file with these settings:
spring:
application:
name: user-service # Service name (used for discovery)
server:
port: 8081 # Port for the user-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/ # Eureka Server URL
instance:
prefer-ip-address: true # Use IP instead of hostname for registration
lease-renewal-interval-in-seconds: 30 # Heartbeat interval (default: 30s)
lease-expiration-duration-in-seconds: 90 # Time to mark instance as down (default: 90s)4.4 Step 4: Add a REST Endpoint#
Create a simple controller to expose a REST endpoint:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/users/{id}")
public String getUser(@PathVariable Long id) {
return "User " + id + " (from user-service)";
}
}4.5 Step 5: Test Registration#
Start the user-service and refresh the Eureka dashboard (http://localhost:8761). You’ll see USER-SERVICE listed under Instances Currently Registered with Eureka!
5. Advanced Features#
Eureka includes powerful features to handle production-grade scenarios like high availability, zone affinity, and security.
5.1 High Availability (HA) Clusters#
A single Eureka Server is a single point of failure (SPOF). For production, you must run multiple Eureka Servers in a cluster to ensure availability.
How It Works#
Eureka Servers replicate their registry data to each other using peer-to-peer replication. When a client registers with one server, the data is propagated to all peers.
Example: 2-Node Eureka Cluster#
Configure two Eureka Servers (server1 and server2):
Server 1 (Port 8761)#
server:
port: 8761
spring:
application:
name: eureka-server
eureka:
client:
register-with-eureka: true # Register with peer server
fetch-registry: true # Fetch registry from peer
service-url:
defaultZone: http://localhost:8762/eureka/ # Peer server URL
server:
enable-self-preservation: trueServer 2 (Port 8762)#
server:
port: 8762
spring:
application:
name: eureka-server
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8761/eureka/ # Peer server URL
server:
enable-self-preservation: trueClient Configuration#
Update your Eureka Client to point to both servers:
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/When you start both servers, they will replicate their registries. If one server goes down, the other continues to serve clients.
5.2 Zone Affinity#
In multi-region deployments, you can use zone affinity to:
- Prefer services in the same geographic zone (reduces latency).
- Isolate failures to a single zone.
Configuration#
Add a zone metadata tag to your client:
eureka:
instance:
metadata-map:
zone: us-east-1 # Assign client to the us-east-1 zone
client:
prefer-same-zone-eureka: true # Prefer instances in the same zone
availability-zones:
us-east-1: http://eureka-us-east-1:8761/eureka/ # Map zone to server URLs
us-west-2: http://eureka-us-west-2:8762/eureka/5.3 Custom Metadata#
You can attach custom key-value pairs to Eureka instances for filtering or routing. For example:
Client Configuration#
eureka:
instance:
metadata-map:
version: v1 # Custom metadata: service version
environment: production # Custom metadata: deployment environmentFetching Metadata#
Use the DiscoveryClient to filter instances by metadata:
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.beans.factory.annotation.Autowired;
@Autowired
private DiscoveryClient discoveryClient;
public List<ServiceInstance> getV1Instances() {
return discoveryClient.getInstances("user-service")
.stream()
.filter(instance -> "v1".equals(instance.getMetadata().get("version")))
.collect(Collectors.toList());
}5.4 Health Checks#
By default, Eureka uses heartbeats to determine if an instance is healthy. For more granular health checks (e.g., database connectivity), integrate Spring Boot Actuator.
Step 1: Add Actuator Dependency#
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>Step 2: Enable Health Checks#
Update your client configuration:
management:
endpoints:
web:
exposure:
include: health,info # Expose health and info endpoints
eureka:
client:
healthcheck:
enabled: true # Use Actuator health instead of default heartbeatsEureka will now use the /actuator/health endpoint (HTTP 200 = UP, 503 = DOWN) to mark instances as healthy or unhealthy.
5.5 Securing Eureka#
To prevent unauthorized access to the Eureka Server, add basic authentication (or OAuth2 for production).
Step 1: Add Security Dependency#
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>Step 2: Configure Credentials#
Update the Eureka Server’s application.yml:
spring:
security:
user:
name: admin # Username
password: secret # PasswordStep 3: Update Client URLs#
Clients must include credentials in the Eureka Server URL:
eureka:
client:
service-url:
defaultZone: http://admin:secret@localhost:8761/eureka/6. Best Practices#
Follow these best practices to ensure a reliable Eureka deployment:
6.1 Use Meaningful Service Names#
The spring.application.name is the primary key for service discovery. Use consistent, human-readable names (e.g., user-service instead of svc-123).
6.2 Enable prefer-ip-address#
Set eureka.instance.prefer-ip-address: true to register the client’s IP address instead of its hostname. This avoids DNS resolution issues in containerized environments (e.g., Docker, Kubernetes).
6.3 Tune Heartbeat and Eviction Timers#
Balance between responsiveness (detecting failures quickly) and network load:
lease-renewal-interval-in-seconds: 30 (default) – Don’t go lower than 10s.lease-expiration-duration-in-seconds: 90 (default) – Should be 3x the renewal interval.eureka.server.eviction-interval-timer-in-ms: 60000 (default) – Time between eviction checks.
6.4 Run Eureka Servers in HA Mode#
Never run a single Eureka Server in production. Use at least 2 servers in a cluster to ensure high availability.
6.5 Secure the Eureka Server#
Always enable authentication (basic auth/OAuth2) for the Eureka Server. Unauthorized access could allow attackers to register fake services or disrupt your microservices.
6.6 Monitor Eureka with Actuator#
Enable Spring Boot Actuator for both Eureka Servers and Clients:
- Eureka Server: Monitor
/actuator/health(server health) and/actuator/eureka-server(registry stats). - Eureka Client: Monitor
/actuator/discoveryclient(client status) and/actuator/health(instance health).
6.7 Avoid Hardcoding URLs#
Never hardcode service URLs in your code. Use Eureka to discover services dynamically:
// Bad: Hardcoded URL
String userServiceUrl = "http://localhost:8081/users/1";
// Good: Dynamic discovery
String userServiceUrl = "http://user-service/users/1";7. Common Issues & Troubleshooting#
Here are solutions to the most common Eureka problems:
7.1 Instance Not Registering#
- Cause: Missing Eureka Client dependency, incorrect
defaultZone, or the client is unhealthy. - Fix:
- Verify the
spring-cloud-starter-netflix-eureka-clientdependency is present. - Check that
eureka.client.service-url.defaultZonepoints to a running Eureka Server. - Ensure the client’s
/actuator/healthendpoint returnsUP.
- Verify the
7.2 Stale Instances#
- Cause: The Eureka Server hasn’t evicted an instance that’s shut down.
- Fix:
- Tune
eureka.server.eviction-interval-timer-in-ms(reduce to 30s for faster eviction). - Ensure the client sends a deregister request on shutdown by configuring
server.shutdown=gracefulandspring.cloud.service-registry.auto-registration.enabled=true, or use@PreDestroyfor manual deregistration.
- Tune
7.3 Eureka Server Not Starting#
- Cause: Incompatible Spring Cloud/Spring Boot versions.
- Fix: Use a compatible version pair. For example:
- Spring Boot 3.2.x → Spring Cloud 2023.0.x (Illford).
- Spring Boot 2.7.x → Spring Cloud 2021.0.x (Jubilee).
7.4 Client Not Discovering Services#
- Cause: Stale cache, incorrect service name, or the server is unreachable.
- Fix:
- Wait 30 seconds for the client to refresh its cache.
- Verify that the service name in the client’s
spring.application.namematches the name used in discovery. - Check network connectivity between the client and Eureka Server.
8. Example Use Case: Microservices with Eureka#
Let’s build a complete example with two microservices:
user-service: Registers with Eureka and exposes a/users/{id}endpoint.order-service: Discoversuser-servicevia Eureka and calls its endpoint.
8.1 Step 1: Set Up Eureka Server#
Follow Section 3 to create a 2-node Eureka Cluster (ports 8761 and 8762).
8.2 Step 2: Build user-service#
Use the client setup from Section 4, with this controller:
@RestController
@RequestMapping("/users")
public class UserController {
private static final Map<Long, User> USERS = new HashMap<>();
static {
USERS.put(1L, new User(1L, "John Doe", "[email protected]"));
USERS.put(2L, new User(2L, "Jane Smith", "[email protected]"));
}
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
return USERS.containsKey(id)
? ResponseEntity.ok(USERS.get(id))
: ResponseEntity.notFound().build();
}
// User record (Java 16+)
public record User(Long id, String name, String email) {}
}8.3 Step 3: Build order-service#
Create a new Eureka Client with these dependencies:
- Spring Cloud Eureka Client
- Spring Web
- Spring Boot Actuator
Configure a Load-Balanced RestTemplate#
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced // Enables Ribbon load balancing
public RestTemplate restTemplate() {
return new RestTemplate();
}
}Add a Controller to Discover user-service#
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/{id}/user")
public ResponseEntity<User> getOrderUser(@PathVariable Long id) {
// Assume order 1 is linked to user 1
Long userId = 1L;
String userServiceUrl = "http://user-service/users/" + userId;
User user = restTemplate.getForObject(userServiceUrl, User.class);
return user != null
? ResponseEntity.ok(user)
: ResponseEntity.notFound().build();
}
// Reuse the User record from user-service
public record User(Long id, String name, String email) {}
}8.4 Step 4: Test the Workflow#
- Start both Eureka Servers.
- Start
user-service(port 8081) andorder-service(port 8082). - Navigate to the Eureka dashboard (http://localhost:8761) to confirm both services are registered.
- Call the
order-serviceendpoint:curl http://localhost:8082/orders/1/user - You’ll get a response from
user-servicevia Eureka:{"id":1,"name":"John Doe","email":"[email protected]"}
9. Conclusion#
Spring Cloud Netflix Eureka is a mature, battle-tested service discovery tool for Spring Boot microservices. It simplifies the complexities of dynamic service registration and discovery while providing features like high availability, zone affinity, and health checks.
Key takeaways:
- Eureka Server: Central registry for service metadata.
- Eureka Client: Registers services and discovers others via the server.
- Best Practices: Use HA clusters, secure the server, and tune timers for production.
- Integration: Works seamlessly with other Spring Cloud components (Ribbon for load balancing, Hystrix for circuit breaking).
While Eureka is in maintenance mode (Netflix stopped active development in 2018), it remains widely used in Spring Boot ecosystems. For new projects, consider alternatives like Spring Cloud Consul or Spring Cloud Zookeeper, but Eureka is still a solid choice for existing Spring Cloud deployments.
10. References#
- Spring Cloud Netflix Documentation
- Eureka GitHub Repository
- Spring Boot Actuator Documentation
- Spring Security Documentation
- Netflix Eureka Wiki
Let me know if you have any questions—happy to help!