Spring Boot
Spring Cloud
Spring Cloud is an umbrella project that provides production-ready building blocks for microservices on the JVM. It integrates with Spring Boot to deliver service discovery (Eureka), API gateway (Spring Cloud Gateway), client-side load balancing (Spring Cloud LoadBalancer), distributed configuration (Spring Cloud Config), circuit breaking (Resilience4j), and distributed tracing (Micrometer Tracing / Zipkin).
Spring Cloud Overview and BOM
Spring Cloud is not a single library β it is a collection of sub-projects versioned together under a release train (e.g. 2023.0.x for Spring Boot 3.x). The Bill of Materials (BOM) pins compatible versions of all sub-projects so you never have to manage individual library versions. Import the BOM once in pom.xml and then declare individual starters without version tags.
XML
<!-- pom.xml β import Spring Cloud BOM: -->
<properties>
<java.version>21</java.version>
<spring-cloud.version>2023.0.3</spring-cloud.version>
</properties>
<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>
<!-- Individual starters β no <version> needed: -->
<dependencies>
<!-- Service discovery client (registers with Eureka): -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- API Gateway: -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Centralised configuration: -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!-- Circuit breaker (Resilience4j integration): -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<!-- OpenFeign declarative HTTP client: -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
// ββ Spring Boot β Spring Cloud version compatibility: ββββββββββββββββ
// Spring Boot 3.2.x / 3.3.x β Spring Cloud 2023.0.x (Leyton)
// Spring Boot 3.0.x / 3.1.x β Spring Cloud 2022.0.x (Kilburn)
// Spring Boot 2.7.x β Spring Cloud 2021.0.x (Jubilee)
// Always verify at: https://spring.io/projects/spring-cloudKey Spring Cloud Components
Spring Cloud composes several focused sub-projects. Each solves a distinct microservices concern. You include only the starters you need β there is no requirement to use all components together.
Java
// ββ Spring Cloud component map ββββββββββββββββββββββββββββββββββββββββ
//
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// β CLIENT / BROWSER β
// βββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
// β
// βΌ
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// β Spring Cloud Gateway (API Gateway) β
// β β’ Route requests to downstream services β
// β β’ Auth filters, rate limiting, SSL termination β
// ββββββββββββ¬ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββ
// β β
// βΌ βΌ
// ββββββββββββββββββββ ββββββββββββββββββββ
// β User Service β β Order Service β ...more services
// β @DiscoveryClientβ β @DiscoveryClientβ
// ββββββββββ¬ββββββββββ ββββββββββ¬ββββββββββ
// β β
// ββββββββββββ¬ββββββββββββ
// β register / lookup
// βΌ
// βββββββββββββββββββββββββββββββββββββββββββ
// β Spring Cloud Netflix Eureka (Registry) β
// β β’ Tracks all live service instances β
// βββββββββββββββββββββββββββββββββββββββββββ
//
// Supporting components (used inside each service):
//
// Spring Cloud Config β externalise application.yml to a Git repo
// Spring Cloud LoadBalancerβ client-side load balancing across instances
// Spring Cloud OpenFeign β declarative REST client (@FeignClient)
// Resilience4j β circuit breaker, retry, rate limiter
// Micrometer Tracing β distributed tracing (exports to Zipkin/Tempo)
// ββ Component responsibilities at a glance: βββββββββββββββββββββββββββ
// Gateway β WHERE do requests go?
// Eureka β WHERE is each service running right now?
// Config Server β WHAT configuration does each service use?
// LoadBalancer β WHICH instance handles this request?
// OpenFeign β HOW does service A call service B?
// Resilience4j β WHAT happens when service B is down?
// Micrometer β HOW do we trace a request across services?Spring Cloud Config Server
Spring Cloud Config Server externalises configuration for all microservices into a central Git repository. Each service fetches its configuration on startup (and optionally at runtime via /actuator/refresh). This eliminates per-service application.yml files scattered across repos and enables environment-specific config (dev, staging, prod) without rebuilding images.
Java
// ββ Config Server setup: βββββββββββββββββββββββββββββββββββββββββββββ
// pom.xml (config-server module only):
// <dependency>
// <groupId>org.springframework.cloud</groupId>
// <artifactId>spring-cloud-config-server</artifactId>
// </dependency>
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
// application.yml (Config Server):
// server:
// port: 8888
// spring:
// cloud:
// config:
// server:
// git:
// uri: https://github.com/your-org/microservices-config
// default-label: main
// search-paths: '{application}' # look in a folder per service
// ββ Git repo structure (microservices-config): βββββββββββββββββββββββ
// microservices-config/
// βββ application.yml β shared defaults for ALL services
// βββ user-service/
// β βββ application.yml β user-service defaults
// β βββ application-dev.yml β user-service dev overrides
// β βββ application-prod.yml β user-service prod overrides
// βββ order-service/
// βββ application.yml
// βββ application-prod.yml
// ββ Config Client (every microservice): ββββββββββββββββββββββββββββββ
// pom.xml:
// <dependency>
// <groupId>org.springframework.cloud</groupId>
// <artifactId>spring-cloud-starter-config</artifactId>
// </dependency>
// bootstrap.yml (loaded before application.yml):
// spring:
// application:
// name: user-service # determines which file is fetched
// config:
// import: "configserver:http://localhost:8888"
// profiles:
// active: dev # fetches user-service/application-dev.yml
// ββ Config Server REST API (built-in): βββββββββββββββββββββββββββββββ
// GET /{application}/{profile}[/{label}]
//
// http://localhost:8888/user-service/dev
// http://localhost:8888/user-service/prod/main
// Returns merged config: application.yml + user-service.yml + profile overrideOpenFeign Declarative HTTP Client
Spring Cloud OpenFeign lets you call another microservice by writing an interface annotated with @FeignClient β no RestTemplate or WebClient boilerplate. Feign integrates automatically with Eureka (resolves service names) and Spring Cloud LoadBalancer (client-side load balancing), and can wrap calls with Resilience4j circuit breakers.
Java
// pom.xml:
// <dependency>
// <groupId>org.springframework.cloud</groupId>
// <artifactId>spring-cloud-starter-openfeign</artifactId>
// </dependency>
// ββ Enable Feign on the main application class: βββββββββββββββββββββββ
@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication { ... }
// ββ Declare the Feign client interface: βββββββββββββββββββββββββββββββ
// 'name' matches spring.application.name of the target service.
// Eureka resolves the name to a real host:port at runtime.
@FeignClient(
name = "user-service",
fallback = UserClientFallback.class // optional circuit breaker fallback
)
public interface UserClient {
@GetMapping("/api/users/{id}")
UserResponse findById(@PathVariable Long id);
@PostMapping("/api/users")
UserResponse create(@RequestBody CreateUserRequest request);
@GetMapping("/api/users")
List<UserResponse> findAll(
@RequestParam(required = false) String role
);
}
// ββ Fallback (used when UserService is down): βββββββββββββββββββββββββ
@Component
public class UserClientFallback implements UserClient {
@Override
public UserResponse findById(Long id) {
return UserResponse.builder().id(id).name("Unknown").build();
}
@Override
public UserResponse create(CreateUserRequest request) {
throw new ServiceUnavailableException("user-service is down");
}
@Override
public List<UserResponse> findAll(String role) {
return Collections.emptyList();
}
}
// ββ Inject and use in a service: βββββββββββββββββββββββββββββββββββββ
@Service
@RequiredArgsConstructor
public class OrderService {
private final UserClient userClient; // Feign proxy injected by Spring
public OrderResponse placeOrder(CreateOrderRequest req) {
UserResponse user = userClient.findById(req.getUserId());
// Feign handles: HTTP call, serialisation, load balancing, retries.
Order order = orderRepository.save(Order.from(req, user));
return OrderResponse.from(order);
}
}
// ββ application.yml β enable Feign + Resilience4j fallbacks: βββββββββ
// spring:
// cloud:
// openfeign:
// circuitbreaker:
// enabled: true