Microservizi
Tutti i microservizi che compongono la piattaforma devo rispettare i seguenti standard e regole generali
Last updated
Was this helpful?
Tutti i microservizi che compongono la piattaforma devo rispettare i seguenti standard e regole generali
Last updated
Was this helpful?
Tutti i servizi devono rispettare i , descritti in modo anche più dettagliato nell'articolo
Ogni microservizio deve poter essere eseguito facilmente in locale, anche da chi non conosce a fondo il progetto. L’obiettivo del packaging è:
facilitare l’avvio dell’applicativo;
semplificare lo sviluppo e il debugging;
rendere accessibile un ambiente funzionante con un semplice docker-compose up
.
Nella root del repository devono essere presenti i seguenti file:
Dockerfile
Build dell’immagine base del servizio
docker-compose.yml
Definisce i container minimi per l’esecuzione in produzione o ambienti CI
docker-compose.dev.yml
Contiene configurazioni utili per lo sviluppo locale (es. build
, mount volumi, strumenti debug)
.dockerignore
(opzionale) Esclude file e cartelle non rilevanti dalla build
Il file docker-compose.yml
deve essere autosufficiente: chi lo scarica deve poter eseguire il servizio senza dover clonare l’intero repository.
Le immagini Docker utilizzate devono essere:
disponibili su un registry pubblico (es. DockerHub, GitHub Container Registry ecc.);
oppure facilmente costruibili in locale tramite override.
⚠️ Non includere la chiave
build:
neldocker-compose.yml
principale, per evitare conflitti nei contesti di esecuzione remota (es. CI/CD).
Per lo sviluppo in locale:
Copia o rinomina il file docker-compose.dev.yml
in docker-compose.override.yml
Esegui:
✅ In questo modo, chiunque può avviare l’ambiente di sviluppo senza modificare i file originali.
docker-compose.yml
(semplificato)
docker-compose.dev.yml
Dopo aver rinominato docker-compose.dev.yml
in docker-compose.override.yml
, il comando:
...utilizzerà in automatico l’immagine build
locale con i volumi montati per lo sviluppo.
Ogni microservizio deve essere in grado di gestire correttamente la terminazione, in modo da:
garantire la consistenza dei dati;
evitare la perdita di eventi o operazioni incomplete;
chiudere le risorse in uso in maniera sicura (DB, Kafka, file, socket...).
La gestione corretta della terminazione è essenziale sia in ambiente Docker che in Kubernetes, dove il segnale di terminazione (SIGTERM
) viene inviato prima di un restart o di un downscaling.
SIGTERM
Richiesta di terminazione gentile
Il servizio avvia lo shutdown controllato
SIGKILL
Terminazione forzata e immediata
Non gestibile dal codice; da evitare
✅ Il servizio DEVE catturare
SIGTERM
e avviare una sequenza di terminazione controllata.
Alla ricezione di SIGTERM
, il servizio deve:
smettere di accettare nuove richieste o eventi;
completare le operazioni critiche in corso;
liberare risorse (connessioni, file, lock...);
loggare la terminazione a livello INFO
;
uscire con exit code 0 entro un tempo ragionevole.
Cattura SIGTERM
Il servizio intercetta correttamente il segnale SIGTERM
☐
Terminazione controllata
Avvia una sequenza di chiusura ordinata
☐
Timeout ragionevole
Si chiude in max 10s (o valore configurato)
☐
Operazioni critiche completate
Nessuna perdita o corruzione dati
☐
Chiusura delle risorse
Socket, consumer, file, connessioni DB...
☐
Log di terminazione
Esempio: "SIGTERM ricevuto, shutdown in corso..."
☐
Nessuna nuova richiesta
I listener vengono disattivati
☐
Exit code 0
Il processo si chiude correttamente
☐
uvicorn + asyncio
signal.NotifyContext
Usare questo script per validare la terminazione pulita in locale o integrarlo nella CI.
Se si usa docker-compose
, si può integrare il test nel CI lanciando:
La configurazione dei microservizi deve avvenire:
principalmente tramite variabili d’ambiente;
opzionalmente tramite:
file .env
(per ambienti locali);
parametri CLI (per job schedulati o debug interattivo).
Variabili d’ambiente
Default per tutti i deployment (prod/dev/test)
.env
file
Sviluppo locale o test manuali
CLI parametri
Script cron, job schedulati, test/debug
❗ Le configurazioni non devono essere hardcoded nel codice. Utilizzare sempre default sicuri e sovrascrivibili.
Permettere al sistema di orchestrazione (Docker/Kubernetes) di verificare che il servizio sia vivo e funzionante.
Deve esporre un endpoint /status
:
200 OK
se tutto è funzionante;
codice diverso in caso di errore.
Se il servizio non è HTTP, l’healthcheck può essere:
la presenza di un file di stato;
la verifica di un processo in esecuzione.
✅ L’healthcheck DEVE essere incluso nel
Dockerfile
.
Tutti i microservizi devono implementare un sistema di log coerente, strutturato e facilmente aggregabile.
I log devono supportare almeno i livelli: DEBUG
, INFO
, ERROR
. Una gestione completa prevede sei livelli (vedi sotto).
Ogni log di errore o anomalia deve essere su una singola riga, facilmente parsabile (plaintext key=value
o JSON).
Evitare log verbosi e non strutturati: ostacolano il monitoraggio e la correlazione cross-microservizio.
⚠️ Non mischiare log di tipo HTTP e stacktrace multilinea.
Scrivere i log a singola riga su
stdout
.Scrivere stacktrace (se necessario) separatamente su
stderr
.
Preferibile l’uso di log in formato JSON puro, ma solo se interamente strutturato.
È vietato:
Mischiare testo libero e JSON nello stesso log.
Includere payload JSON grezzi come stringa in un campo JSON (es. loggare interamente l’evento Kafka).
timestamp
✅
event_id
✅
Identificatore univoco dell’evento (per correlazione)
event_type/operation
✅
Tipo di evento o operazione ricevuta
call_type
⚠️
Tipo chiamata: HTTP
, CLI
, BATCH
topic
✅
Kafka topic da cui è stato letto l’evento (se applicabile)
microservice
✅
Nome del microservizio che ha generato il log
error
/ detail
✅
Messaggio di errore leggibile
client_ip
⚠️
IP della chiamata in ingresso. Usare X-Forwarded-For
quando presente
tenant
, provider
, application
, service
✅
Contesto operativo (se disponibili)
user_id
❌
Se presente, deve essere un riferimento anonimo (es. ID utente). Mai dati personali in chiaro
All’avvio, ogni servizio DEVE loggare la versione in esecuzione e l’ambiente (es. local
, boat-qa
, boat-prod
).
CRITICAL
Fallimento grave, con perdita di dati o che comporta lo l'uscita dal flusso di esecuzione (shutdown) del servizio per impossibilità a proseguire o perché è più safe non proseguire.
No
ERROR
Anomalia che non è possibile gestire e che avrà effetti sul risultato. A ERROR, il rate dei log che si alza dovrebbe essere indice che ci sono problemi per i quali è importante attrarre l'attenzione degli amministratori. Attenzione a non confondere errori che si verificano su sistemi esterni e che non sono nostri errori. Date sempre per scontato che una riga di errore prodotta dovrebbe sempre essere letta da qualcuno, altrimenti meglio esporre un livello di warning o non loggare proprio. Una anomalia dovrebbe sempre dare origine a una e una sola riga di log.
Si
WARNING
Anomalia che non avrebbe dobuto presentarsi ma che è stata gestita correttamente per non comportare errori nel nostro servizio. Ad esempio ho ricevuto un evento con una versione negativa, ma l'ho ignorato. Oppure non sono riuscito a collegarmi al db la prima volta, ma solo dopo 2 tentativi.
Si
INFO
Comunica un cambiamento di stato del servizio. Un evento significativo produce una riga di log per ogni evento o chiamata ricevuta dall'applicativo. Se una transazione o un evento gestito presenta errori NON si deve produrre la riga di INFO e la riga di ERROR, ma solo la seconda.
Si
DEBUG
Questo è il livello in cui comunicare informazioni diagnostiche, non necessarie se non si sta investigando un errore specifico. Devono essere informazioni utili a comprendere errori, non semplicemente a comprendere il flusso interno del software, per il quale esiste il livello apposito (TRACE). Una informazione utile è dare tutto il contesto che permette di comprendere perché il servizio si sta comportando in un certo modo.
No
TRACE
Questo livello è inteso per tracciare il flusso interno del servizio, in modo molto dettagliato. Per esempio si può inserire un log a questo livello per capire in quale ramo del codice siamo finiti con l'esecuzione, oppure si può inserire una riga all'inizio e una alla fine di certe porzioni di codice rilevanti.
No
✅ Ogni anomalia deve generare una e una sola riga di log a INFO, i dettagli vanno a DEBUG.
JSON strutturato
Plaintext key=value
ERROR
Usare questa checklist in review e PR:
Raccogliere centralmente gli errori per individuare rapidamente problemi in produzione.
Una volta configurato:
abilitare l’integrazione con Sentry;
definire regole di alert personalizzate, se quelle standard non bastano.
📬 Usare
SENTRY_DSN
come variabile d’ambiente per collegare il servizio a Sentry.
Esportare metriche di stato e performance per il monitoraggio continuo.
Se HTTP, il microservizio DEVE esporre un endpoint /metrics
in formato Prometheus.
Error counters
✅
Numero errori critici/intermittenti
Response histograms
✅
Tempi di risposta di servizi esterni
Status code metrics
⚠️
Solo se utili (es. 500 frequenti) – altrimenti usiamo Traefik
404 o bot traffic
❌
NON deve essere esposto come metrica – produce rumore inutile
Non reinventare un sistema di schedulazione dentro l’applicazione. Usare invece l’orchestratore.
NON implementare schedulatori interni (es. cron manuale, loop time-based).
Il servizio deve essere idempotente: rieseguibile sugli stessi dati senza effetti collaterali.
Implementare task cron come comandi CLI, eseguibili con la stessa immagine Docker:
Niente overengineering: Docker impone già un mapping tra esterno e interno.
Path interni
Usa path fissi tipo /data
, senza preoccuparsi del mapping esterno
Configs
Secrets
NO volumes
Evitare l’uso di volume mapping per la configurazione
✅ Questo approccio garantisce sicurezza, semplicità e prevedibilità.
Standardizzare la CI tra i progetti, garantendo efficienza, velocità e qualità.
Ogni progetto DEVE includere la CI condivisa:
Eventuali step personalizzati (es. test, lint, coverage) vanno inseriti dopo lo include
.
Durata massima della CI: 15 minuti
Durata consigliata: ≤ 5 minuti
⚡ Ottimizzare usando:
test selettivi.
publiccode.yml
Docker gestirà automaticamente il merge tra docker-compose.yml
e docker-compose.override.yml
(vedi: ).
Riferimento normativo: .
In UTC, formato , con T
e Z
maiuscoli
Ogni microservizio DEVE integrare .
Il job verrà poi schedulato tramite clustered cron (es. ).
Usare per file di configurazione
Usare per credenziali e dati sensibili
Devono riutilizzare la build già fatta tramite , evitando rebuild inutili.
build Docker;
;
Per progetti pubblicati su :