Introduction
This blog post explores the integration of Eureka and Spring Cloud Config in a microservices architecture. It covers how services register with Eureka, how client-to-client communication is handled using RestTemplate and FeignClient, and how configuration properties are managed using Spring Cloud Config Server with a Git repository.
Microservices Architecture and Challenges
Microservices architecture is a design approach where an application is composed of small, independent services that communicate over well-defined APIs. Each microservice is responsible for a specific business capability and can be developed, deployed, and scaled independently.
While microservices offer flexibility and scalability, they also introduce several challenges:
- Service discovery: Identifying the location of services dynamically.
- Load balancing: Distributing requests across multiple instances.
- Configuration management: Managing configuration across services.
Eureka – Service Discovery
Eureka is a service discovery tool provided by Netflix, used in Spring Cloud for locating services for the purpose of load balancing and failover of middle-tier servers. Each microservice registers itself with the Eureka server, and the server maintains a registry of all available services.
Eureka Configuration
Eureka Server Configuration:
- Add dependency: spring-cloud-starter-netflix-eureka-server
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
- Annotate main class with @EnableEurekaServer
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
- Configure application.yml/application.properties with server port and instance details
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
Eureka Client Configuration:
- Add dependency: spring-cloud-starter-netflix-eureka-client
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- Annotate main class with @EnableDiscoveryClient
@SpringBootApplication
@EnableDiscoveryClient
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
- Configure application.yml with Eureka server URL and instance name
spring:
application:
name: order-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
How Eureka Solves Microservices Challenges
Eureka addresses many of the challenges in a microservices architecture:
- Service Registration and Discovery: Services register themselves with Eureka Server and can discover other services using Eureka Client.
- Load Balancing: Eureka integrates with Ribbon and Spring Cloud Load Balancer to distribute requests across service instances.
- Health Checks: Eureka monitors service health and removes unhealthy instances from the registry.
For example, when microservice A wants to communicate with microservice B, it queries Eureka for B’s location. Eureka would return the available instances, and A can use RestTemplate or FeignClient to make the call.
Below is an image of the Eureka dashboard showing registered services:
Client-to-Client Communication
Using RestTemplate with LoadBalancer
RestTemplate can be used with Spring Cloud LoadBalancer to make client-to-client calls.
The service name is used instead of the actual URL, and the load balancer resolves the
service instance.
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
Usage:
String response = restTemplate.getForObject(
“http://payment-service/payments/123”, String.class);
Using RestTemplate without LoadBalancer
Without a load balancer, RestTemplate would require the actual name of the target service registered on the Eureka server, and manual selection of instances would be required to make a call, making it less flexible and harder to manage in dynamic environments.
Usage:
@GetMapping(“/resttemplate-direct”)
public String callAccountService() {
RestTemplate restTemplate = new RestTemplate();
String serviceUrl = discoveryClient.getInstances(“ACCOUNT-
SERVICE”).stream().findFirst()
.map(si -> si.getUri().toString()).orElseThrow(() -> new RuntimeException(“Service
not found”));
return restTemplate.getForObject(serviceUrl + “/account/resttemplate”,
responseType: String.class);
}
Using Feign Client
Feign is a declarative web service client that makes writing web service clients easier. It
integrates with Eureka and Ribbon to provide load-balanced HTTP calls using simple
interfaces.
Usage:
@FeignClient(name = “payment-service”)
public interface PaymentClient {
@GetMapping(“/payments/{id}”)
Payment getPayment(@PathVariable String id);
}
Spring Cloud Config – Centralized Configuration
Spring Cloud Config provides server and client-side support for externalized configuration in a distributed system. The Config Server fetches configuration properties from a Git repository and serves them to client applications.
Spring Cloud Config Configuration
Config Server Setup:
- – Add dependency: spring-cloud-config-server
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
- – Annotate main class with @EnableConfigServer
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
- – Configure application.yml with Git repository URL
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: https://github.com/your-org/config-repo
Config Client Setup:
- – Add dependency: spring-cloud-starter-config
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
- – Configure bootstrap.yml with config server URL and application name
spring:
application:
name: order-service
cloud:
config:
uri: http://localhost:8888
Each microservice connects to the Config Server at startup to retrieve its configuration. This allows centralized management of configuration and dynamic updates without redeploying services.
Conclusion
Combining Eureka and Spring Cloud Config provides a robust foundation for building scalable and maintainable microservices. Eureka simplifies service discovery and load balancing, while Spring Cloud Config centralizes configuration management, making it easier to manage and update services in a distributed environment. Together, they make distributed systems easier to manage, scale, and evolve.