📁
.net CMS
Sviluppatori > Moduli

Pipeline

Modulo che crea un canale di comunicazione per l’invio di messaggi di notifica nell’ambito multi server

Quando una applicazione gira su più server contemporaneamente, sorge il problema che oggetti mantenuti in cache possono non essere aggiornati quando un singolo server ne modifica uno, occorre quindi un sistema che mantenga sincronizzati tutti gli oggetti preservati nella cache di ogni singolo server, a tale scopo viene utile il modulo dal nome “Pipeline”.
Si pensi per esempio a cosa dovesse avvenire in una applicazione che gira in coinfigurazione multi-server, se in un forum, un utente dovesse modificare un topic e questo sia mantenuto in una ram cache: Succederebbe che questo dato sarà aggiornato solo sul server in cui è avvenuto il cambiamento, mentre invece tutti gli altri server manterranno  in cache una versione del topic risalente a prima della modifica.
Il modulo pipeline mette a disposizione due semplici metodi per la sincronizzazione di elementi mantenuti in una cache, i quali sono:

AddActionForNotification(ByVal Element As Type, ByVal Action As NotifyChangementDelegate)
Questo metodo serve a monitorizzare un elemento nella cache, a ad impartire una azione nel tal caso questo elemento venisse modificato o rimosso da uno dei server su cui gira l’applicazione. Si immagini ad esempio ad una cache formata da una matrice di diversi oggetti dove ad ogni oggetto è associata una chiava (un ID univoco), se un oggetto con un determinato ID cambia, sarà opportuno eseguire su tutti i server una azione che elimini dalla cache questo oggetto che non è più aggiornato. Il paramento Action è appunto il delegato alla funzione che dovrà efeguire l’azione di espellere dalla cache l’oggetto non più sincronizzato. Questo delegato ha un solo parametro, ed è la chiave (ovvero l’ID univoco) dell’oggetto da espellere dalla cache. Il parametro Element, sta ad indicare invece il tipo di elemento che è mantenuto in cache.

NotifyChangement(ByVal Element As System.Type, ByVal Id As String)
Questo è l’altro metodo molto importante e serve a notificare a tutti i server che un elemento di un determinato tipo, mantenuto in cache è stato modificato o rimosso. In questo caso su tutti i server verrà eseguito il metodo impostato per mezzo di AddActionForNotification il quale provvederà alla rimozione dalla cache dell’oggetto non più aggiornato.

Questo meccanismo di sincronizzazione che rende possibile un perfetto funzionamento della applicazione in configurazione multi-server, è molto più semplice da capirsi che da spiegarsi. A chi interessato si consiglia di dare uno sguardo direttamente al sorgente dell’applicativo web in che modo queste due funzioni sono state utilizzate.

Lo sviluppatore software, nell’ambito della realizzazione di plugin o personalizzazioni per il nostro applicativo web, dovrebbe ipotizzare che la propria realizzazione dovrà girare nelle configurazioni hardware più disparate e a volte anche disperate! Con il fine di rendere le proprie implementazioni compatibili con lo spettro più ampio possibile di configurazioni hosting e server, è opportuno mirare sempre nello scrivere routine che innanzitutto siano in grado di girare – per quanto riguarda la security policy – con un trust level Medium, e che non siano affette da problemi su configurazioni hosting di tipo multi server.
Il questa sessione, vogliamo occuparci esclusivamente degli strumenti che – tramite il modulo Pipeline – sono stati messe a disposizione dello sviluppatore per ciò che riguarda il corretto funzionamenti di routine su configurazioni multi server, ovvero ci occuperemo del corretto funzionamento delle estensioni e plugin dell’applicativo, su server multipli che in parallelo – creando più istanze dell’applicativo, una per ogni macchina – gestiscano l’attività web in maniera indipendentemente .
Il funzionamento di un qualsiasi applicativo web, in configurazione multi server può essere afflitto da anomalie ogni qualvolta un dato mantenuto in una memoria locale – come per esempio potrebbe un informazione conservata in una collection o cache, una istanza di oggetto in ram, eccetera – necessiti d’essere sincronizzato sulle altre macchine. Proprio con il fine di sincronizzare i dati gestiti in memoria locale dall’applicativo su tutte le macchine in cui gira, abbiamo a disposizione i metodi AddActionForNotification e NotifyChangement forniti dal modulo Pipeline, modulo che per tutti gli sviluppatori, togliendo per essi le castagne dal fuoco, sarà una vera e propria goduria. Occorre precisare infatti, che comunicare tra server in una configurazione di tipo hosting multi server come quella fornita dalla quasi totalità degli internet provider, è cosa ardua non essendovi ne collegamenti di rete accessibili, ne alcun tipo di protocollo di comunicazione tra macchine, lo sviluppatore che tuttavia realizza le proprie opere sottoforma di plugin nell’ambito di questa applicazione web, non se ne dovrà affatto preoccupare in quanto si troverà a disposizione tutto ciò di cui necessita, reso fruibile in maniera intuitiva e persino parsimoniosa per quel che riguarda la quantità di codice da implementare per una totale integrazione.
Il primo metodo che prendiamo in esame è AddActionForNotification, il quale nell’ambito del ciclo di vita dell’applicazione, dovrà essere eseguito una sola volta per tipo di oggetto all’avvio e serve a stabilire che azione (ovvero quale procedura) dovrà essere lanciata ogni qualvolta si riceverà la notifica che un determinato oggetto abbia subito una modifica da un altro server su cui gira l’applicativo. La sintassi è molto semplice:

Sub AddActionForNotification(Element As Type, Action As NotifyChangementDelegate)

Il parametro Element passa il tipo di oggetto su cui si sta lavorando, mentre Action passa un riferimento alla procedura che dovrà essere avviata alla notifica di un cambiamento del tipo di oggetto settato con il primo parametro.
Portiamo come esempio pratico una casistica reale, in cui è stato usato questo sistema di notifica per la realizzazione del cuore del applicativo web.
Premessa: Essendo questo un applicativo in grado di gestire siti su più domini, dispone per ogni dominio di una specifica configurazione, ciò proprio affinché ogni dominio possa disporre di configurazioni differenti. Per accedere più velocemente alle configurazioni di dominio, queste vengono mantenute in ram per mezzo di una collection dictionary. Quando una qualsiasi configurazione di dominio viene cambiata e salvata su un server, gli altri server su cui girano le altre istanze dell’applicativo dovranno essere avvisati, in modo da eliminare dalla collection dictionary la configurazione che è stata modificata rimpiazzandola con quella già salvata dal server che ha apportato la modifica.
Da notare, che – in tutto questo ambaradan –  non abbia alcuna importanza su quanti siano i server su cui l’applicativo stia girando, come non rivesta alcuna importanza quale sia il server che apporta la modifica. Ci limitiamo a specificare che in qualsiasi caso, il server che apporterà la modifica logicamente sarà sempre quello che in quel momento sta interagendo con l’utente collegato via browser, per noi la cosa sarà del tutto indifferente e di conseguenza ce ne possiamo sbattere...
Nel nostro esempio, inizializziamo il meccanismo in questo modo:

AddActionForNotification(GetType(DomainConfiguration), AddressOf ChangedByAnotherServer)

Con l’istruzione sopra andiamo a dire che se su un altro server in cui sta girando l’applicativo dovesse cambiare una istanza di tipo  DomainConfiguration, vogliamo essere avvisati tramite l’esecuzione del metodo ChangedByAnotherServer. Metodo che ha un solo parametro ed è la chiave dell’elemento che è stato cambiato, nel nostro esempio la chiave corrisponde al nome di dominio che ha subito un cambiamento di configurazione,  il metodo ChangedByAnotherServer è il seguente:

Public Shared Sub ChangedByAnotherServer(ByVal Domain As String)
 SyncLock AllDomainConfiguration
  If AllDomainConfiguration.ContainsKey(Domain) Then
   AllDomainConfiguration.Remove(Domain)
  End If
 End SyncLock

End Sub

In pratica, ogni qualvolta che un server modificherà la configurazione di un dominio (elemento di tipo DomainConfiguration), su tutti glia altri server verrà eseguita la proceduta ChangedByAnotherServer(Domain) la quale provvederà a rimuovere la configurazione di dominio dalla collection AllDomainConfiguration essendo questa una configurazione non più valida, quindi mantenerla in memoria andrebbe a ledere il corretto funzionamento dell’applicativo.
Per far si che AddActionForNotification venga eseguito esclusivamente una sola volta quando opportuno, ovvero una sola volta al momento del caricamento modulo che ne fa uso, è stato utilizzato un semplice espediente che consiste in questo breve codice:

Private Shared EnableServerNotification As Boolean = StartupServerNotification()
Private Shared Function StartupServerNotification() As Boolean
AddActionForNotification(GetType(DomainConfiguration), AddressOf ChangedByAnotherServer)
 Return True

End Function

In pratica è stata creata una funzione StartupServerNotification con il compito esclusivo di eseguire AddActionForNotification, tale funzione viene utilizzata per passare un valore a EnableServerNotification e quindi verrà lanciata in automatico all’inizializzazione del modulo.
Viso come impostare l’azione da eseguire su notifica di cambiamento da parte degli altri server, vediamo ora invece l’altro aspetto complementare, ovvero come un server effettua la notifica agli altri ogni qualvolta un elemento viene modificato. A tale scopo si utilizzerà il metodo NotifyChangement la cui sintassi è:

Public Sub NotifyChangement(Element As System.Type, Id As String)

Il parametro Element passa il tipo di elemento che si è appena modificato e che quindi si intende aggiornare sugli altri server, mentre il secondo parametro Id, è la chiave univoca a lui associata.
Tornando al nostro esempio, quando una configurazione di dominio viene modificata e salvata, dovrà essere inviata notifica a tutti i server affinché si aggiornino. Tale notifica che la inneschiamo con il metodo NotifyChangement, la inseriamo al termine del metodo Save dell’oggetto DomainConfiguration tramite la semplice l’istruzione seguente:

Sub Save(Optional ByVal Domain As String = Nothing) 
 Rem Qui ci vanno le istruzioni per i salvataggio dell’istanza di DomainConfiguration
 Rem Il sistema più semplice per salvare un oggetto, è ricorrere a SaveObject
 NotifyChangement(GetType(DomainConfiguration), Domain)

End Sub

Nell’esempio sopra riportato, assistiamo al classico caso in cui un oggetto modificato viene salvato dopodiché per mezzo di NotifyChangement viene notificata tale variazione a tutti gli altri server su cui gira l’applicativo. Ogni server riceverà immediatamente notifica, la quale si manifesterà con l’esecuzione del metodo ChangedByAnotherServer (metodo impostato all’avvio tramite AddActionForNotification), che come abbiamo visto sopra andrà ad eliminare dalla memoria (ovvero dalla collection) una configurazione non più valida.
Il nostro esempio si propone di  rappresentare una spiegazione esaustiva inerente l’impiego della Pipeline, tuttavia si suggerisce agli sviluppatori a cui ancora qualche aspetto non fosse chiaro o a coloro che volessero approfondire l’argomento, di vedere in che modo i metodi AddActionForNotification e NotifyChangement siano stati impiegato all’interno dell’applicativo web, per fare ciò dall’editor di Visual Web Developer, basta posizionarsi con il cursore su uno dei metodi in oggetto e premere Shift + F12.

Argomenti nella stessa categoria