En el mundo de los microservicios, la diferencia entre una implementación promedio y una excepcional está en los detalles. Hoy exploraremos patrones avanzados que transformarán la manera en que construyes microservicios con Spring Boot 3.2.
Requisitos Previos
Para seguir este tutorial necesitarás:
- Java 21
- Spring Boot 3.2
- Docker instalado
- Conocimientos básicos de microservicios
Comencemos con el Código Base
@SpringBootApplication
@EnableCircuitBreaker
public class MicroserviceApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceApplication.class, args);
}
@Bean
public CircuitBreakerRegistry circuitBreakerRegistry() {
return CircuitBreakerRegistry.ofDefaults();
}
}
¿Por qué este setup inicial? Simple:
- Habilitamos Circuit Breaker desde el inicio
- Configuramos el registro por defecto
- Preparamos la aplicación para patrones de resiliencia
Implementando Circuit Breaker
@Service
@Slf4j
public class ProductService {
private final CircuitBreaker circuitBreaker;
private final RestTemplate restTemplate;
public ProductService(CircuitBreakerRegistry registry) {
this.circuitBreaker = registry.circuitBreaker("productService");
this.restTemplate = new RestTemplate();
}
public Product getProduct(String id) {
return circuitBreaker.executeSupplier(() -> {
String url = "http://product-api/products/" + id;
return restTemplate.getForObject(url, Product.class);
});
}
}
Este patrón nos proporciona:
- Protección contra fallos en cascada
- Recuperación automática
- Monitoreo integrado
- Timeouts inteligentes
Service Discovery con Eureka
@SpringBootApplication
@EnableEurekaClient
public class ProductServiceApplication {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@RestController
@RequestMapping("/api/products")
public class ProductController {
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/{id}")
public Product getProduct(@PathVariable String id) {
// Obtener instancia del servicio dinámicamente
List<ServiceInstance> instances =
discoveryClient.getInstances("product-service");
if (instances.isEmpty()) {
throw new ServiceNotFoundException();
}
ServiceInstance instance = instances.get(0);
String url = instance.getUri().toString() + "/products/" + id;
// Realizar llamada al servicio
return restTemplate.getForObject(url, Product.class);
}
}
Beneficios de este enfoque:
- Descubrimiento automático de servicios
- Balanceo de carga incorporado
- Escalado dinámico
- Alta disponibilidad
Configuración Distribuida
@Configuration
@EnableConfigServer
public class ConfigServerApplication {
@Bean
public JGitEnvironmentRepository gitEnvironmentRepository() {
JGitEnvironmentRepository repo = new JGitEnvironmentRepository(null);
repo.setUri("https://github.com/tu-repo/config");
return repo;
}
}
// En el microservicio cliente
@RefreshScope
@RestController
public class ConfigurationController {
@Value("\${custom.property}")
private String customProperty;
@GetMapping("/config")
public String getConfig() {
return customProperty;
}
}
Este sistema nos permite:
- Cambios de configuración en caliente
- Versionamiento de configuración
- Rollback sencillo
- Configuración por ambiente
Monitoreo y Observabilidad
@Configuration
public class ObservabilityConfig {
@Bean
public MeterRegistry meterRegistry() {
return new SimpleMeterRegistry();
}
@Bean
public TimedAspect timedAspect(MeterRegistry registry) {
return new TimedAspect(registry);
}
}
@Service
public class OrderService {
private final MeterRegistry registry;
@Timed(value = "order.processing.time")
public Order processOrder(Order order) {
// Lógica de procesamiento
registry.counter("orders.processed").increment();
return processedOrder;
}
}
Este setup nos proporciona:
- Métricas en tiempo real
- Trazabilidad de operaciones
- Alertas automáticas
- Dashboards informativos
Conclusiones y Mejores Prácticas
Al implementar estos patrones, recuerda:
- Comenzar con Circuit Breakers desde el inicio
- Implementar Service Discovery temprano
- Mantener la configuración centralizada
- Monitorear todo
Recursos Recomendados
Para profundizar en estos conceptos, recomiendo:
- “Cloud Native Java” – Esencial para microservicios en Java
- “Spring Microservices in Action” – Patrones prácticos