Spring Cloud microservices patterns with gateway, discovery, and resilience
Spring Cloud microservices patterns with gateway, discovery, and resilience
Build distributed microservices architectures using Spring Cloud Gateway, service discovery, configuration management, and resilience patterns.
Configure API Gateway for routing and cross-cutting concerns:
// GatewayApplication.java
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
// application.yml
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/orders/**
filters:
- StripPrefix=1
- name: CircuitBreaker
args:
name: orderServiceCircuitBreaker
fallbackUri: forward:/fallback/orders
// GatewayConfig.java
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("user-service", r -> r
.path("/api/users/**")
.filters(f -> f
.addRequestHeader("X-Gateway-Request", "true")
.retry(retryConfig -> retryConfig
.setRetries(3)
.setMethods(HttpMethod.GET)
.setBackoff(Duration.ofMillis(100), Duration.ofSeconds(2), 2, false)
)
)
.uri("lb://user-service"))
.build();
}
@Bean
public GlobalFilter customGlobalFilter() {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
ServerHttpRequest modifiedRequest = request.mutate()
.header("X-Gateway-Timestamp", String.valueOf(System.currentTimeMillis()))
.build();
return chain.filter(exchange.mutate().request(modifiedRequest).build());
};
}
}
Set up Eureka server and client registration:
// EurekaServerApplication.java
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
// eureka-server application.yml
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
// UserServiceApplication.java (Client)
@SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
// user-service application.yml
spring:
application:
name: user-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
Centralized configuration management:
// ConfigServerApplication.java
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
// config-server application.yml
spring:
cloud:
config:
server:
git:
uri: https://github.com/org/config-repo
search-paths: '{application}'
clone-on-start: true
// Client application.yml
spring:
cloud:
config:
uri: http://localhost:8888
name: user-service
profile: dev
Implement circuit breaker pattern:
// UserServiceClient.java
@Service
public class UserServiceClient {
private final RestTemplate restTemplate;
private final CircuitBreaker circuitBreaker;
public UserServiceClient(RestTemplate restTemplate, CircuitBreakerRegistry circuitBreakerRegistry) {
this.restTemplate = restTemplate;
this.circuitBreaker = circuitBreakerRegistry.circuitBreaker("userService");
}
@CircuitBreaker(name = "userService", fallbackMethod = "getUserFallback")
public User getUser(Long id) {
return circuitBreaker.executeSupplier(() ->
restTemplate.getForObject("http://user-service/api/users/{id}", User.class, id)
);
}
public User getUserFallback(Long id, Exception ex) {
return User.builder()
.id(id)
.name("Fallback User")
.email("fallback@example.com")
.build();
}
}
// Resilience4jConfig.java
@Configuration
public class Resilience4jConfig {
@Bean
public CircuitBreakerRegistry circuitBreakerRegistry() {
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofMillis(1000))
.slidingWindowSize(10)
.build();
return CircuitBreakerRegistry.of(config);
}
@Bean
public TimeLimiterRegistry timeLimiterRegistry() {
return TimeLimiterRegistry.of(TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofSeconds(3))
.build());
}
}
Set up Micrometer Tracing with Zipkin:
// pom.xml
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
</dependency>
// application.yml
management:
tracing:
sampling:
probability: 1.0
zipkin:
tracing:
endpoint: http://localhost:9411/api/v2/spans
// TracingConfig.java
@Configuration
public class TracingConfig {
@Bean
public Sender sender() {
return OkHttpSender.create("http://localhost:9411/api/v2/spans");
}
@Bean
public AsyncReporter<Span> spanReporter() {
return AsyncReporter.create(sender());
}
}
Implement event-driven microservices:
// OrderService.java
@Service
public class OrderService {
private final StreamBridge streamBridge;
public OrderService(StreamBridge streamBridge) {
this.streamBridge = streamBridge;
}
public void createOrder(Order order) {
// Process order
orderRepository.save(order);
// Publish event
streamBridge.send("orderCreated-out-0", OrderCreatedEvent.builder()
.orderId(order.getId())
.userId(order.getUserId())
.totalAmount(order.getTotalAmount())
.timestamp(Instant.now())
.build());
}
}
// NotificationService.java
@SpringBootApplication
@EnableBinding(Sink.class)
public class NotificationService {
@StreamListener(Sink.INPUT)
public void handleOrderCreated(OrderCreatedEvent event) {
// Send notification
notificationService.sendEmail(event.getUserId(),
"Order " + event.getOrderId() + " created");
}
}
// application.yml
spring:
cloud:
stream:
bindings:
orderCreated-out-0:
destination: order-created
binder: kafka
input:
destination: order-created
group: notification-service
kafka:
binder:
brokers: localhost:9092
{directories.knowledge}/spring-microservices-patterns.jsondeveloping-spring-boot for service implementationobserving-spring-apps for monitoring and metricsThis skill should be used when strict adherence to the defined process is required.
Category:other