I pattern dell’inventario dei servizi che verranno descritti in questo articolo sono stati catalogati in una sorta di sottofamiglie, di modo da mettere in evidenza con un livello di dettaglio ulteriori le rispettive problematiche per le quali possono essere chiamati in causa.
In particolare vedremo la sottofamiglia che mette insieme i pattern per la definizione dei confini dello stesso inventario, quella per la struttura e la centralizzazione della logica business, la sottofamiglia di pattern che ci consente di migliorare l‘implementazione “fisica” dell‘inventario e quella relativa alla modalità di governance.
Pattern per i confini dell’inventario
Come già spiegato nel primo articolo di questa serie, un inventario è una collezione di servizi supportata da un’architettura tecnologica. Un passo fondamentale nella sua realizzazione è la definizione dello scope del servizio in relazione all’enterprise dentro la quale esso avrà una parte. Come illustra la figura 1, i pattern Enterprise Inventory e Domain Inventory stabiliscono i limiti dell’inventario dei servizi; va precisato che, in una enterprise IT è possibile applicarne solo uno per volta.
Figura 1 – Pattern per i confini dell’inventario.
Una sostanziale differenza tra l’Enterprise Inventory e il Domain Inventory è che l’obiettivo del primo sta nel definire un singolo inventario di servizi che si estende alle esigenze dell’enterprise, mentre l’obiettivo del Domain sta nella possibilità di poter definire più inventari (di solito abbastanza limitati) che coesistono all’interno della stessa enterprise.
Enterprise Inventory
All’interno della stessa enterprise possono essere realizzati vari progetti, ciascuno dei quali con i propri obiettivi, i propri servizi e le tecnologie a supporto, rispondenti ai requisiti richiesti. Il risultato, molto spesso, è quello di avere dei cluster di servizi definiti inizialmente per i progetti specifici, in cui le differenze implementative possono portare a vari problemi nel momento in cui si richiede di comporre i servizi in nuove configurazioni, che vanno oltre i confini dell’architettura iniziale.
Figura 2 – Pattern Enterprise Inventory.
La soluzione è quella di definire un’architettura service-oriented che faccia da supporto all’inventario di servizi, di modo che possano rispondere a più soluzioni all’interno di una enterprise. Una volta definiti dei servizi che sono indipendenti e rispondono agli standard implementativi, non si rischia di avere possibili problemi di integrazione nel momento in cui si richiede di ricombinare gli stessi, anche se inizialmente devono rispondere a progetti specifici, realizzati da team differenti.
Domain Inventory
In enviroment di notevoli dimensioni risulta spesso insufficiente avere un singolo inventario a sostegno di tutta l’enterprise. Vediamo quali sono i problemi che ostacolano il mantenimento di un solo inventario di servizi in presenza delle prospettive appena date.
Dal punto di vista del Project Manager ci sarebbero troppi standard restrittivi per realizzare i progetti in maniera efficiente e con budget ragionevoli; secondo gli architetti IT, l’architettura risulterebbe troppo complessa e porterebbe l’IT ad ignorare la buona pratica del design standard; secondo gli sviluppatori, ci sarebbero così tanti progetti concorrenti da non poter essere sicuri che magari un team non stia realizzando magari proprio quello che viene sviluppato in contemporanea da un altro team. Insomma, le ragioni contrarie al singolo inventario a sostegno di tutta l’enterprise non mancano.
Da qui l’esigenza di definire più di un inventario di servizi, rispondente ciascuno a un determinato dominio business. Avere più inventari porta dei vantaggi come quelli di avere una facile scalabilità dell’architettura nel momento in cui si ha, per esempio, l’esigenza di dover evolvere solo un inventario che risponde a un certo dominio business; occorre però sempre prestare attenzione nell’evolvere i servizi appartenenti ai singoli domini per evitare possibili ridondanze di servizi.
Pattern sulla struttura dell’inventario
Questa serie di pattern che introduciamo di seguito aiuta a definire la struttura di un inventario di servizi: si tratta di pattern come il Service Normalization e il Logic Centralization. Questi pattern, in pratica, richiedono che i servizi futuri siano in linea con gli altri già presenti; in particolar modo, ci si assicura che i servizi business vengano posizionati come unico endpoint per la logica che rappresentano.
Service Normalization
L’applicabilità di questo pattern nasce dal fatto che, anche se i confini di un inventario sono stati delimitati, c’è il rischio costante che i servizi che vengono realizzati abbiano una certa sovrapposizione di funzionalità, soprattutto se consegnati a diversi gruppi di sviluppo. In queste situazioni si cade nella de normalizzazione dell’inventario, che può causare problemi quali:
- impossibilità nello stabilire le funzionalità dei servizi come endpoint unici;
- architettura più complessa in cui più servizi forniscono la stessa funzionalità ma in differenti modi.
La soluzione proposta a questa problematica sta nel modellare i servizi prima di definire il loro contratto. Questo dà a ciascun servizio la possibilità di essere pianificato di modo che la sua logica non vada a sovrapporsi con quella degli altri servizi dell’inventario. Il risultato è quello di avere un alto grado di normalizzazione delle funzionalità. Per arrivare a questo grado di definizione, occorre identificare i processi business appartenenti all’inventario, allocare le rispettive parti del processo come servizi candidati e verificare che non ci siano sovrapposizioni.
Logic Centralization
All’interno di un inventario, può sorgere il problema di non individuare dei servizi possibilmente “riusabili” da altri servizi dello stesso inventario. Questo porta a replicare le stesse funzionalità in più servizi, ricadendo nella problematica della ridondanza e sovrapposizione di logica.
Per perseguire allora l’obiettivo del riuso di un servizio, occorre riuscire a classificare quei servizi riusabili di modo che la loro logica sia accessibile:
Figura 3 – Pattern Logic Centralization.
Come illustra la figura 3, se all’interno di più composizioni di servizi che fanno parte dell’inventario vi sono delle logiche comuni, occorre identificarle e candidarle come servizio riusabile; inoltre, se vi sono delle nuove funzionalità che possono ricadere nei confini di un servizio già esistente, questa funzionalità deve essere aggiunta al servizio, piuttosto che crearne uno nuovo.
Service Layers
Uno dei possibili problemi di un inventario sta anche nella “tipologia” di logica incapsulata dai servizi che appartengono a tale inventario. Molto spesso, si può cadere nell’errore di realizzare i servizi facendovi rientrare varie tipologie di logica, perdendo dunque la possibilità di riusare il servizio ed eventualmente di farlo evolvere:
Figura 4 – Logiche diverse incapsulate nello stesso servizio.
Come illustra la figura 4, uno stesso servizio rischia di incapsulare logiche di varie tipologie, intese come logiche che potrebbero appartenere a differenti layer architetturali.
La soluzione a questo problema sta nel realizzare i servizi secondo dei modelli, ciascuno dei quali rappresenta un set di caratteristiche associate a un tipo di layer all’interno del quale possono essere posizionati i servizi stessi. La definizione dei possibili layer deve essere individuata a priori all’interno dell’inventario. Pertanto, i servizi devono coprire una certa tipologia di logica di modo da rispondere alle caratteristiche di un layer già individuato.
Figura 5 – Pattern Service Layer.
L’applicazione del pattern, come illustra la figura 5, permette di realizzare dei servizi rispondenti singolarmente a logiche di business, di entità e di utilità, senza mescolare le stesse all’interno di un unico servizio.
Pattern di centralizzazione dell’inventario
Questa sezione è invece dedicata a quei pattern che coprono più gli aspetti fisici dell’architettura dell’inventario dei servizi.
Process centralization
Ci possono essere situazioni in cui, all’interno dello stesso inventario, la logica business non sia localizzata in un singolo servizio task ma in diversi servizi, che poi vengono esposti ad esempio come web services. Il problema si pone se questi processi cominciano a essere distribuiti in varie locazioni e in seguito devono essere evoluti e mantenuti.
Per risolvere questa situazione, i servizi possono continuare ad essere implementati come web services, ma diventano parte di una piattaforma che ne permette l’orchestrazione, di modo che la loro logica sia distribuita su un’unica piattaforma e possa essere mantenuta. L’applicazione dell’orchestrazione non è necessariamente richiesta per la centralizzazione del processo; l’applicazione della logica di più processi business in un singolo servizio task può invece essere considerata la realizzazione di questo pattern detto Process Centralization.
Rules Centralization
Molto spesso i processi business sono guidati da specifiche “business rules” (sono le regole della logica applicativa): in certi casi, le medesime regole potrebbero essere comuni a più processi dello stesso inventario. Se queste regole vengono incapsulate nell’implementazione di ciascun processo si ricade nel problema della ridondanza, con l’inconveniente inoltre di dover modificare ciascun processo nel momento in cui queste regole variano: e sappiamo bene come le regole siano proprio soggette a possibili e frequenti cambiamenti.
La soluzione consiste nell’astrarre fisicamente queste regole in una sezione dedicata dell’architettura, sotto la gestione di specifici motori di regole. In ciò consiste il pattern Rules Centralization. Questo consente di centralizzarle in maniera che i vari processi che ne fanno uso possano poi accedere ad esse indipendentemente, quando necessario. Oggigiorno esistono svariati sistemi di gestione delle regole business, ma un’altra alternativa sarebbe quella di definire un servizio come punto d’accesso per la creazione, la modifica e il ritiro delle stesse regole. Questo tipo di servizio rientra nel layer dei servizi di utility poiche’ fornirebbe una funzionalità generica e perche’ il contesto funzionale non deriverebbe da nessun modello business specifico dell’organizzazione.
Pattern dell’implementazione dell’inventario
Questa sezione introduce i pattern che aiutano nella risoluzione dei problemi a livello implementativo dell’inventario.
Dual Protocols
Il pattern Canonical Protocol definisce che diversi gruppi di servizi devono avere una sola tecnologia di comunicazione come mezzo per poter interagire. Ci possono però essere situazioni in cui, all’interno dell’inventario, un solo protocollo di comunicazione non è sufficiente; o comunque quello scelto risulta inadeguato per certi tipi di scambi di dati.
La soluzione a questo problema sta prima di tutto nel discernere due livelli di servizi all’interno dell’inventario:
- un livello primario che si basa sul protocollo preferito;
- un livello secondario che si basa sul protocollo alternativo.
Un esempio di protocollo di comunicazione che non si presta bene a tutte le esigenze è per esempio il SOAP su HTTP. Questo perche’:
- il SOAP introduce un certo overhead nell’elaborazione dei messaggi e risulterebbe poco ragionevole per servizi che devono scambiare dati di grossa granularità o che devono essere invocati più volte dallo stesso consumer all’interno dello stesso processo;
- il servizio potrebbe richiedere una funzionalità particolare non supportata dalla piattaforma tecnologica di un determinato fornitore.
Pertanto, il pattern Dual Protocols fornisce un compromesso che si basa praticamente sulla standardizzazione di due protocolli canonici. Per esempio, quando si applica questo pattern a un inventario di servizi web-based, i servizi realizzati come web services sono tipicamente classificati come i servizi di livello primario.
Quando però i web services non rispondono a tutte le esigenze, viene scelto un protocollo secondario e, molto comunemente, quest’alternativa si basa su una certa piattaforma di componenti come Java.
In tal modo, dei servizi primari, come i web services, possono coesistere con dei servizi secondari, come i componenti, ed entrambi rappresentano degli endpoint ufficiali. La comunicazione tra questi due livelli di servizi è concessa mediante i rispettivi contratti. Si potrebbe pensare di bypassare il contratto quando, per esempio, la logica del servizio primario supporta lo stesso protocollo del servizio secondario, ma ciò è un anti-pattern che va contro i principi dell’applicazione di questo pattern.
State Repository
Nel corso dell’attività di un servizio è spesso necessario recuperare e mantenere in cache dei dati ai quali le funzioni di un servizio richiedono di accedere. Comunque, alcune composizioni complesse possono introdurre lunghi periodi di tempo in cui i dati cached non vengono richiesti. Durante quesa attività di idle però, i dati continuano ad essere mantenuti in memoria e consumano delle risorse a runtime.
La soluzione consiste nel definire un repository dello stato per ciascun servizio di modo da evitare che questi mantengano in memoria i dati dello stato per lunghi periodi di tempo. Mantenendo i dati in un repository, il servizio può transitare in una condizione stateless mentre la sua attività è in pausa, liberando temporaneamente le risorse di sistema. Questo è lo scopo del pattern State Repository.
Tipicamente, per l’applicazione di questo pattern viene utilizzato un database localizzato sullo stesso server in cui risiedono i servizi che lo stanno utilizzando, di modo da minimizzare l’overhead delle performance correlate con la scrittura e il recupero dei dati. La figura 6 illustra l’utilizzo di repository.
Figura 6 – Esempio di pattern State Repository.
Il servizio Policy Check effettua la prima richiesta al servizio Policy TypeA e scrive il risultato nel repository, prima di richiedere i dati al servizio Policy TypeB. Dopo la richiesta a questo secondo servizio, le informazioni vengono ancora depositate sul repository e dopo l’ultima invocazione al servizio Policy TypeC, il Policy Check recupera i dati dello stato presenti sul repository e li assembla per definire la richiesta iniziale di Policy Report.
Stateful services
In una composizione di servizi, spetta al servizio di task layer mantenere e gestire lo stato di tutte le attività dei servizi, sino a quando l’attività non è stata completata. Delegare la gestione dello stato di tutto il processo business a un solo servizio è non solo una certa responsabilità da parte del servizio ma inoltre riduce la possibilità di scalabilità dello stesso:
Figura 7 – Problema di task services con stato.
La soluzione consiste nel creare dei servizi stateful anche a livello di utility di modo da fornire sempre le funzionalità di storage delle informazioni ma allo stesso tempo ridurre la responsabilità di gestione dello stato ad un singolo servizio a livello task:
Figura 8 – Pattern Stateful Services.
Inventory endpoint
Un inventario di servizi rappresenta una collezione di servizi realizzati e governati in maniera indipendente. Quando però aumentano le richieste da parte di consumer esterni per l’utilizzo delle funzionalità di questi servizi, aumentano anche i problemi di sicurezza, di interoperabilità e di privacy degli stessi.
Se infatti dei consumer esterni accedono in maniera diretta al codice nativo delle funzionalità introducono dei rischi notevoli. Occorre quindi che per ogni inventario venga scelto un servizio che funga da entry point alle funzionalità offerte dall’inventario. Questo endpoint deve essere configurato per rispondere alle preferenze di interazione dei consumer esterni, e deve inoltre contenere una logica di mediazione che faciliti la comunicazione coi servizi dell’inventario.
Pattern di governance dell’inventario
Questa sezione introduce i pattern che permettono la governance dell’inventario dei servizi. In questa categoria rientrano il pattern di centralizzazione dei metadati e quello di versionamento canonico.
Metadata centralization
Quando un inventario dei servizi tende a espandersi in termini di numero di servizi, c’è sempre il rischio che i team dei progetti realizzino inavvertitamente nuovi servizi o funzionalità di servizi già esistenti o che semplicemente siano in sovrapposizione con quelle già esistenti. Questo andrebbe contro i principi dei pattern di Logic Centralization e di Service Normalization. Per evitare simili inconvenienti, la soluzione sta nello stabilire un registry dei servizi come parte centrale dell’infrastruttura di modo che sia possibile:
- registrare i servizi esistenti e le rispettive funzionalità;
- registrare i servizi e le funzionalità in sviluppo.
Come illustra la figura 9, il processo di discovery di un servizio consiste nel localizzare un potenziale servizio mediante un registry, in cui vengono registrati per esempio i servizi presenti in un inventory, e di interpretarlo per definirne la sua disponibilità:
Figura 9 – Pattern Metadata Centralization.
Il pattern Metadata Centralization è chiaramente connesso al pattern di discovery di un servizio. L’applicazione di questo pattern richiede:
- l’applicazione regolare del pattern di discovery di un servizio ai contratti di tutti i servizi presenti nell’inventario;
- l’utilizzo dei profili del servizio per standardizzare la documentazione del servizio e i metadati delle funzionalità: per esempio, una parte comune dei profili è l’utilizzo di un vocabolario usato per le parole chiave, associate a ciascun record del service registry;
- la realizzazione di un service registry a supporto dell’infrastruttura.
Canonical Versioning
Quando i contratti di un servizio, all’interno di un inventario, sono soggetti a differenti approcci di versionamento e convenzioni, possono emergere problemi di incompatibilità e di goveranance del servizio stesso. Questo può impattare in maniera negativa nello sviluppo del consumer, nell’accesso a runtime del servizio, nella sua riusabilità e nella totale evoluzione dell’inventario stesso.
Il pattern Canonical Versioning suggerisce la scelta di un’unica convenzione di versionamento e questa dipende anche dalla complessità della stessa enterprise e dalle metodologie di versionamento a disposizione.
Conclusioni
Questo articolo ha messo in evidenza le possibili problematiche che si possono riscontrare quando all’interno di una enterprise si cerca di applicare un approccio service-oriented. Uno dei primi passi sta per l’appunto nel definire l’insieme dei servizi che devono rispondere alle esigenze business dell’IT: a risolvere i problemi che possono crearsi con gli inventari di servizio, la governance SOA mette a disposizione una serie di pattern che vengono a sostegno nella definizione dello stesso inventario. Negli articoli successivi verranno descritti altri pattern che fanno da supporto ai passi successivi per la definizione di un’architettura SOA-oriented.
Vittoria Caranna è nata a Rimini nel 1982. Lauretasi in Ingegneria Informatica presso l‘Università degli studi di Bologna nel dicembre del 2007, da gennaio 2008 lavora per il Gruppo Imola.
Svolge attività di consulenza, in particolare per quanto riguarda le tematiche architetturali e di processo.