Service Discovery
Implementa service discovery con health checks, resolución DNS-based y service registries para ambientes dinámicos de microservicios.
Nota para desarrolladores hispanohablantes: Esta guía incluye ejemplos y convenciones de nomenclatura adaptadas a equipos que trabajan en español. Cuando existen diferencias significativas en terminología técnica entre el inglés y el español, se indican explícitamente para facilitar la comunicación en equipos multiculturales.
Visión General
El service discovery es el mecanismo por el cual los microservicios se localizan y comunican entre sí en ambientes dinámicos donde las direcciones IP cambian constantemente. En lugar de hardcodear endpoints, los servicios se registran en un registro y los clientes lo consultan para encontrar instancias saludables. Combinado con health checks, habilita sistemas auto-curativos que rutean alrededor de fallas automáticamente.
Cuándo Usar
Usa este recurso cuando:
- Ejecutas microservicios en Kubernetes, ECS o auto-scaling groups donde las IPs son efímeras
- Necesitas failover automático cuando instancias de servicio fallan o se vuelven unhealthy
- Balanceas carga entre múltiples instancias sin actualizaciones manuales de configuración
- Implementas despliegues blue-green o canary releases que requieren routing dinámico de tráfico
Solución
Registro de Servicio con Consul (Go)
import "github.com/hashicorp/consul/api"
func registerService(consulAddr, serviceID, name, host string, port int) error {
config := api.DefaultConfig()
config.Address = consulAddr
client, err := api.NewClient(config)
if err != nil {
return err
}
registration := &api.AgentServiceRegistration{
ID: serviceID,
Name: name,
Address: host,
Port: port,
Check: &api.AgentServiceCheck{
HTTP: fmt.Sprintf("http://%s:%d/health", host, port),
Interval: "10s",
Timeout: "5s",
},
}
return client.Agent().ServiceRegister(registration)
}
DNS-Based Discovery (Kubernetes)
apiVersion: v1
kind: Service
metadata:
name: payment-service
spec:
selector:
app: payment
ports:
- port: 8080
targetPort: 8080
# Los servicios se descubren vía DNS
PAYMENT_URL=http://payment-service:8080
Client-Side Load Balancing con Eureka (Java/Spring)
@SpringBootApplication
@EnableDiscoveryClient
public class OrderService {
@Bean
@LoadBalanced
public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
}
@Service
public class OrderProcessor {
@Autowired
private WebClient.Builder webClientBuilder;
public Mono<PaymentResult> processPayment(PaymentRequest request) {
return webClientBuilder.build()
.post()
.uri("lb://payment-service/payments")
.bodyValue(request)
.retrieve()
.bodyToMono(PaymentResult.class);
}
}
Explicación
Tres patrones de discovery:
| Patrón | Mecanismo | Ideal Para |
|---|---|---|
| Client-side | Cliente consulta registry; elige instancia | Alto performance; language-native |
| Server-side | Load balancer consulta registry; cliente usa una URL | Clientes más simples; control central |
| DNS-based | Nombres de servicio resuelven a IPs vía DNS | Kubernetes; zero cambios en clientes |
Integración de health checks:
- Los servicios se registran con un endpoint de health
- El registry hace polling de health checks periódicamente
- Las instancias unhealthy se remueven del pool
- Los clientes cachean datos del registry y refrescan ante fallas
Variantes
| Herramienta | Modelo | Lenguaje | Características Destacadas |
|---|---|---|---|
| Consul | Client + server | Cualquiera | Multi-datacenter; KV store; ACLs |
| Eureka | Client-side | Java | Netflix OSS; integración Spring |
| etcd | Server-side | Cualquiera | Default de Kubernetes; consenso Raft |
| Zookeeper | Server-side | Cualquiera | Maduro; consistencia fuerte |
| AWS Cloud Map | Server-side | Cualquiera | AWS-native; integración ECS |
Mejores Prácticas
- Heartbeat con TTL: Los servicios deben renovar su registro o ser auto-deregistrados
- Cache con fallback: Los clientes deben cachear listas de instancias y usar datos stale brevemente si el registry no está disponible
- Routing zone-aware: Preferir instancias en la misma AZ para reducir latencia y costos de transferencia de datos
- Metadata para routing: Etiquetar instancias con versiones para habilitar canary y A/B testing
- Seguridad con mTLS: Encriptar comunicación service-to-service; autenticar servicios registrados. Consulta API security checklist.
Errores Comunes
- Sin health checks: Instancias muertas no deregistradas siguen recibiendo tráfico
- Thundering herd: Todos los clientes consultando el registry simultáneamente bajo carga
- Ignorar deregistration: Servicios crashados permanecen en el pool hasta que expire el TTL
- Hard-codear fallback IPs: Anula el propósito del discovery dinámico
- Omitir retries: Una instancia fallida debería disparar un retry en otra, no fallar el request. Usa retry con backoff exponencial para clientes resilientes.
Preguntas Frecuentes
P: ¿Debo usar client-side o server-side discovery? R: Client-side es más rápido (sin hop extra) pero requiere clientes inteligentes. Server-side es más simple pero agrega latencia. DNS-based es el más simple para Kubernetes.
P: ¿Cómo funciona el service discovery con serverless? R: AWS Cloud Map, GCP Service Directory o service registries de API Gateway se integran con Lambda y Cloud Run. Aprende más en arquitectura serverless.
P: ¿Cuál es la diferencia entre service discovery y load balancing? R: El discovery encuentra instancias disponibles; load balancing distribuye tráfico entre ellas. A menudo trabajan juntas.
Recursos Relacionados
Microservices Architecture — When to Use and When Not To
A practical guide to microservices: benefits, trade-offs, common patterns, and when to choose them over monoliths. Covers decomposition strategies and operational complexity.
GuideMonolith to Microservices — Migration Strategies
A practical guide to decomposing monoliths: strangler fig, branch by abstraction, and incremental extraction patterns that reduce risk and preserve business continuity.
GuideSoftware Architecture Guide
A guide to designing software architecture: monoliths vs microservices, layered architecture, data flow, and technology selection criteria.
RecipeMicroservices Communication Patterns
Choose between synchronous and asynchronous communication patterns for resilient microservices architectures.
DocADR Template
A reusable template for Architecture Decision Records that capture context, decision, and consequences.