Scegliere lo stile architetturale: monolite, N-tier o microservices
In AZ-305 il punto non è “quale stile è migliore in assoluto”, ma quale stile è coerente con i requisiti di rilascio, scalabilità e affidabilità del carico. Un monolite su Azure App Service resta la scelta corretta quando il team è piccolo, il dominio è semplice e il deploy unico non è un collo di bottiglia: massimizza il pilastro Operational Excellence (una sola pipeline, un solo artefatto) e minimizza i costi. L’architettura N-tier (web, business, data separati) è appropriata per applicazioni line-of-business tradizionali con confini chiari fra presentazione e persistenza, spesso migrate “as-is” verso PaaS.
I microservices vanno raccomandati solo quando esiste un driver concreto: scalabilità indipendente di componenti con profili di carico divergenti, rilasci indipendenti per team autonomi, o isolamento dei guasti. In cambio si paga complessità operativa. La domanda d’esame giusta è sempre: il requisito giustifica il costo di frammentazione?
Isolamento e piattaforma di hosting
Il confronto ricorrente riguarda dove eseguire i servizi:
- Azure App Service (multi-tenant): ottimo per web app e API stateless, con scaling e slot di deployment gestiti. Prima scelta se non servono requisiti di isolamento di rete stringenti.
- App Service Environment (ASE v3): raccomandato quando il requisito è isolamento di rete dedicato, integrazione in VNet single-tenant, compliance o carichi ad alto throughput. Non sceglierlo “per default”: aumenta costo e complessità.
- Azure Kubernetes Service (AKS): indicato per orchestrazione di container su larga scala, controllo fine su networking/scheduling e portabilità. Comporta la responsabilità di gestire cluster, upgrade e osservabilità.
- Azure Container Apps: opzione serverless per microservizi containerizzati con scale-to-zero e Dapr integrato, quando non serve il controllo completo di Kubernetes. Spesso la risposta “giusta” quando il requisito è “microservizi senza gestire un cluster”.
Regola pratica d’esame: se lo scenario dice “isolamento di rete + PaaS gestito” → ASE; “serverless event-driven a microservizi” → Container Apps; “controllo cluster / ecosistema Kubernetes esistente” → AKS.
Statelessness e scaling
Il pilastro Reliability del Azure Well-Architected Framework richiede componenti stateless: lo stato di sessione va esternalizzato (Azure Cache for Redis, database, storage) affinché qualsiasi istanza gestisca qualsiasi richiesta e lo scale-out orizzontale sia possibile. Preferire lo scale-out (più istanze) allo scale-up (istanza più grande) per resilienza e per superare i limiti di una singola macchina. Distribuire le istanze su Availability Zones per proteggersi dai guasti di datacenter.
Pattern di resilienza
Nelle comunicazioni distribuite i guasti transitori sono la norma, non l’eccezione:
- Retry con exponential backoff + jitter: per errori transitori, evitando ondate sincronizzate di ritentativi.
- Circuit breaker: interrompe le chiamate verso un servizio in degrado, evitando di saturare risorse e propagare il guasto (fondamentale contro i cascading failure).
- Bulkhead: isola pool di risorse (connessioni, thread) per servizio, così che il collasso di una dipendenza non affami le altre.
Retry e circuit breaker sono complementari: il retry gestisce il guasto breve, il circuit breaker protegge dal guasto prolungato. Delegare questa logica a un service mesh o a Dapr riduce il codice boilerplate.
Il trade-off centrale: flessibilità vs complessità
I microservizi danno agilità di rilascio e scaling mirato, ma introducono osservabilità distribuita come requisito non negoziabile: distributed tracing (Application Insights / OpenTelemetry), correlazione delle richieste e health probe. Senza questo, il debugging diventa impraticabile. Valutare sempre l’impatto sul pilastro Cost Optimization: più servizi significano più superficie operativa, più networking e più overhead.
Trappole tipiche d’esame
- Requisito: microservizi con deploy indipendenti, ma i servizi condividono lo stesso database e si rilasciano insieme → è un distributed monolith: raccomanda database-per-service e confini di dominio ben definiti, altrimenti resta un monolite più fragile.
- Requisito: latenza elevata per pagina che aggrega dati da molti servizi → sintomo di chatty inter-service communication: raccomanda pattern Gateway Aggregation / BFF o eventi asincroni, riducendo le chiamate sincrone a catena.
- Requisito: app PaaS che deve risiedere in una VNet isolata con compliance → non basta App Service con VNet integration: raccomanda App Service Environment v3.
- Requisito: un servizio downstream lento sta saturando l’intera app → applica circuit breaker + bulkhead; il solo retry aggraverebbe la saturazione.
- Requisito: scaling indipendente di un solo componente ad alto carico su un monolite → non frammentare tutto: estrai solo il componente critico come servizio separato (strangler pattern incrementale).