Architettura Microservices: Design, Comunicazione e Deployment
L'architettura microservices divide le grandi applicazioni in servizi piccoli e indipendenti. Questa guida copre i principi di design dei microservices, la comunicazione inter-servizio e le strategie di deployment.
Ultimo aggiornamento:Cos'è i Microservices?
Microservices è un approccio architetturale che divide una singola grande applicazione (monolite) in servizi piccoli, indipendenti e distribuibili.
Ogni servizio implementa una capacità di business specifica. User service, order service, payment service, ecc.
Deployment indipendente: Ogni servizio può essere distribuito indipendentemente. I cambiamenti in un servizio non influenzano gli altri servizi.
Diversità tecnologica: Ogni servizio può usare uno stack tecnologico diverso. Node.js, Python, Go, Java possono lavorare insieme nello stesso sistema.
Comunicazione Inter-Servizio
Sincrona: Comunicazione diretta via REST API o gRPC. Semplice ma crea accoppiamento (dipendenza).
Asincrona: Comunicazione basata su eventi via message queue (RabbitMQ, Kafka, SQS). Fornisce accoppiamento lasco.
API Gateway: Punto di ingresso unico per tutti i servizi. Esegue routing, autenticazione, rate limiting, load balancing.
Service mesh: Strato di infrastruttura che gestisce la comunicazione inter-servizio. Strumenti come Istio, Linkerd forniscono traffic management, observability, security.
Circuit breaker: Previene il cascade failure durante i guasti del servizio. Implementato con Hystrix o resilience4j.
Gestione dei Dati
Database per servizio: Ogni servizio ha il proprio database. Questo preserva l'indipendenza del servizio.
Event sourcing: Memorizza i cambiamenti di stato come eventi. Lo stato può essere ricostruito dall'event store.
CQRS (Command Query Responsibility Segregation): Separa le operazioni di lettura e scrittura. Usate diversi modelli di dati e ottimizzazioni.
Pattern Saga: Gestisci le transazioni distribuite. Via choreography (basato su eventi) o orchestration (coordinatore centrale).
Coerenza dei dati: Accetta eventual consistency. L'eventual consistency è più pratica della strong consistency nei microservices.
Deployment e Scalabilità
Containerizzazione: Impacchetta ogni servizio come container Docker. Orchestra con Kubernetes.
Auto-scaling: Scalabilità automatica basata sul carico del servizio. Usate Kubernetes HPA (Horizontal Pod Autoscaler).
Service discovery: I servizi si trovano dinamicamente. Usate Consul, Eureka o Kubernetes DNS.
Load balancing: Distribuite il carico tra le istanze del servizio. Algoritmi round-robin, least connections o consistent hashing.
Blue-green deployment: Deploy senza tempo di inattività. Eseguite la nuova versione in ambiente parallelo, cambiate il traffico.
Monitoraggio e Osservabilità
Distributed tracing: Tracciate le richieste attraverso i servizi. Usate Jaeger, Zipkin o OpenTelemetry.
Logging centralizzato: Raccogliete tutti i log dei servizi in un luogo centrale (ELK Stack, Loki). Tracciate le richieste con Correlation ID.
Metriche: Raccogliete le metriche dei servizi (Prometheus) e visualizzate (Grafana). Monitorate latenza, tasso di errore, throughput.
Health checks: Ogni servizio dovrebbe esporre un endpoint di salute (/health). Integrate con i probe liveness e readiness di Kubernetes.
Alerting: Definite regole di alert per le metriche critiche. Gestite l'on-call con PagerDuty o Opsgenie.
Anti-Pattern dei Microservices
Monolite distribuito: I servizi sono strettamente accoppiati (tight coupling). Le modifiche sono difficili. Deployment indipendente impossibile.
Database condiviso: Tutti i servizi usano lo stesso database. Questo elimina l'indipendenza del servizio.
Servizi chatty: Troppi chiamate di rete tra i servizi. La latenza aumenta, le prestazioni diminuiscono.
Nano-servizi: Servizi troppo piccoli. L'overhead (rete, serializzazione) supera il beneficio.
Ottimizzazione prematura: Passare ai microservices senza iniziare dal monolite. Iniziate con il monolite, dividete quando necessario.