Gestione code messaggi
Per la gestione delle code messaggi è stato deciso di utilizzare Azure Service Bus, strumento di messaggistica di Azure.
I messaggi sono inviati/ricevuti tramite:
- Argomenti con sottoscrizioni (topics).
Argomenti e sottoscrizioni
Al momento, è necessario creare gli argomenti e le sottoscrizioni manualmente.
Gli standard di nomenclatura sono:
- Argomenti: hanno il nome della classe contratto che andranno a trasmettere (es. eansingolovariazione).
- Topic: seguono la nomenclatura
{nome-applicazione}_{nome-argomento}(es. anagrafiche_eansingolovariazione)
Utilizzo code messaggi
Pubblicazione
Tutti i metodi di pubblicazione hanno la seguente logica comune:
- Connessione: recupera la stringa di connessione dall’appsettings.json
- Nome coda: calcola il nome della coda dal tipo di evento che deve essere inviato e il nome dell’applicazione dall’appsettings.json
I metodi di pubblicazione sulle code di Azure Service Bus sono:
-
Pubblica (Singolo IEvento)
- Scopo: invio di un singolo oggetto di tipo
IEvento. - Flusso:
- Crea un
ServiceBusCliente unServiceBusSender. - Serializza il messaggio in un JSON.
- Invia il messaggio tramite
SendMessageAsync.
- Crea un
- Scopo: invio di un singolo oggetto di tipo
-
PubblicaMultiplo (IEventoMultiplo)
- Scopo: invio di un singolo oggetto di tipo
IEventoMultiplo - Flusso:
- Se necessario divide la lista di eventi ad un valore fisso di elementi
- Serializza il messaggio in un JSON.
- Invia il messaggio tramite
SendMessageAsync.
- Scopo: invio di un singolo oggetto di tipo
-
PubblicaMultiplo (Lista di IEvento)
- Scopo: invio di eventi singoli in una singola chiamata ad azure
- Flusso:
- Accodamento in memoria
- Serializza i singoli IEvento
- Crea ed aggiunge ad una
Queue<ServiceBusMessage>gli eventi in memoria
- Invio Batch
- Crea
ServiceBusMessageBatchper un invio massivo degli eventi - Riempie il batch finché c’è spazio (
TryAddMessage) - Quando il batch è pieno lo invia alla coda Azure
- Ripete questa logica finché la
Queue<ServiceBusMessage>, in memoria, contiene messaggi
- Crea
- Accodamento in memoria
Consumazione
- Consuma (Sincrono e asincrono)
- Scopo: Lettura di un singolo messaggio nelle code messaggi azure
- Flusso:
- Recupero stringa di connessione e nome coda basato sui dati nell’appsettings.json
- Ricezione singolo messaggio
- Deserializzazione json messaggio (se fallisce il messaggio viene messo nelle Dead letter)
- Tramite un
gestoreesterno elabora il messaggio. Gli esiti possibili sono:- Successo: il messaggio viene completato ed eliminato dalla coda
- Fallito: Scatta la logica di Retry
Logica Retry o DeadLettereQueue?
Il sistema implementa una logica di retry personalizzata poiché Service Bus non supporta nativamente retry con delay variabile arbitrario senza bloccare la coda.
Gli step che vengono effettuati sono:
- Determinazione tentativi:
- Recupera dall’appsettings.json
NumeroMassimoTentativiCoda(default 3) - Recupera dal messaggio la proprietĂ custom
RetryCount(defaultDeliveryCount)
- Recupera dall’appsettings.json
- Gestione retry
- DeadLettereQueue se
elaborazione.ritentaè a false OPPURE i tentativi superano il limite - Logica di retry altrimenti
- DeadLettereQueue se
Logica retry con delay crescente
Questa logica implementa il pattern “Clone & Schedule” per ottenere un retry ritardato
- Viene creato un clone del messaggio in errore
- Viene calcolato un scheduling time lineare (delay * tentativi)
- Invio schedulato del messaggio clonato. Il messaggio sarĂ disponibile dopo il ritardo calcolato
- Completamento e cancellazione del messaggio originale, solo se viene inviato il clone
Configurazione Messaggi di errore e retry
Configurazione retry
Nella classe Elaborazione è presente l’attributo Ritenta e il metodo DaRitentare() per la gestione del retry.
DaRitentare(): Metodo di configurazione dell’attributoRitenta. Va utilizzato nei vari flussi che utilizzano le code messaggi per far sì che nel metodoConsuma()venga riaccodato il messaggio in caso di anomalie nel gestore.Ritenta: Attributo utilizzato dal metodoConsuma()per sapere se il messaggio prelevato dalla coda debba essere gestito molteplici volte in caso di errore (es. attesa di import di una entità collegata)
Configurazione messaggi errore
La classe Elaborazione espone l’attributo Eccezione (di tipo Segnalazione). Questo attributo viene utilizzato dal metodo Consuma per prelevare il messaggio di errore da inviare alla coda messaggi.
La gestione del campo Eccezione è data dai metodi statici:
RegistraComeEccezioneGenerica():- Scopo: log interni.
- Messaggio code: “Errore interno”
RegistraComeEccezioneDettagliata()- Scopo: eccezione per il cliente
- Messaggio code: una stringa di dettagli presente nei parametri del metodo, oltre la segnalazione.