Usare code di messaggi in .net core – parte 2: i Background Worker
Ed eccoci al secondo articolo della Serie. Nello scorso appuntamento abbiamo parlato un po’ delle Code di Messaggi, questa volta invece introdurremo i Background Worker.
Giusto per rinfrescare un po’ la memoria, le Code di Messaggi possono essere usate per gestire le comunicazioni asincrone tra microservizi, migliorando resilienza e scalabilitá.
Ora supponiamo di avere un’API per gestire post e tag di un blog. Ad ogni post possono essere associati uno o piú tag. Diciamo pure che abbiamo come strato di persistenza MongoDb con una sola collection “Posts”. Qualcosa di semplice:
{
title: ...,
description: ...,
creationDate: ...,
tags: ["lorem", "ipsum", "dolor"]
}
Funziona bene, le API riescono a gestire un bel po’ di richieste. Tutti sono felici e contenti.
Un giorno peró ci viene chiesto di aggiungere la funzionalitá di “tag-cloud”: in pratica bisogna esporre un nuovo endpoint che restituisce una lista di tutti i Tag con tanto di conteggio dei Post. Qualcosa tipo:
[
{tag: "lorem", posts_count: 42},
{tag: "ipsum", posts_count: 13},
{tag: "dolor", posts_count: 71}
]
Di nuovo nulla di spaziale. Adesso peró la domanda è : come creiamo i dati?
La prima opzione potrebbe essere di aggiungere una nuova collezione per i Tag ed aggiornarne il contenuto con un upsert ogni volta che un Post viene creato o modificato.
Funziona benino ma non é particolarmente scalabile: l’intera operazione potrebbe richiedere tempo oppure fallire e quindi lasciarci con il db in uno stato inconsistente.
Sicuramente potremmo aggiungere un Circuit Breaker ma sono sicuro che non ci toglierebbe completamente dai guai.
Un’altra opzione invece é quella di usare un Background Worker: in soldoni all’avvio dell’applicazione facciamo partire un thread secondario ed eseguire quindi in background qualunque operazione ci serve.
Ovviamente questo thread sará al di fuori del ciclo request/response http quindi non avremo accesso a cose tipo utente loggato, cookie e cosí via.
Tornando al nostro piccolo esempio, il nostro Background Worker si occuperá ad intervalli regolari di svuotare la collezione dei Tag e ricrearla da zero. Potremmo farlo partire ogni 6 ore ad esempio ma questo ovviamente dipende molto dalla frequenza di aggiornamento dei Post.
Visto che stiamo usando MongoDb, potremmo sfruttare un map/reduce oppure l’aggregate pipeline, non fa molta differenza (in veritá si, ma non é il punto oggi).
I Background Worker possono essere usati anche per consumare messaggi pubblicati su una coda: Ad esempio possiamo gestire un evento “Ordine spedito” ed inviare un’email di notifica al cliente.
È un’operazione totalmente asincrona che puó essere fatta offline, al di fuori del contesto web, quindi un candidato perfetto per un Background Worker.
Altra cosa che potremmo fare è gestire l’evento “Post creato” ed aggiornare i dati denormalizzati nel db delle query, ottenendo cosí un’architettura CQRS (magari con persistenza poliglotta).
E per oggi è tutto. La prossima volta le cose si faranno piú interessanti perché andremo ad analizzare un po’ di codice.