MokaByte 88 - 7mbre 2004 

Service Oriented Architecture

Introduzione

di
Marco
Piraccini

L'integrazione di componenti eterogenei e il riutilizzo di applicazioni legacy sono oggi delle necessità importanti nello sviluppo di sistemi in realtà complesse. Il disegno di un sistema in termini di composizione di servizi permette di massimizzare il riuso dei componenti e i Web Services offrono un ottimo strumento per implementare questi concetti

Introduzione
Possiamo definire un'architettura come "un insieme di decisioni significative sull'organizzazione di un sistema software, sulla selezione degli elementi strutturali e sulle interfacce di cui il sistema è composto, insieme con i comportamenti così come specificati nelle collaborazioni tra questi elementi (...)"[1]. Di conseguenza uno stile architetturale deve specificare un insieme di regole per il disegno dei componenti, per la definizione delle relative interfacce e per la definizione delle modalità di interazione tra essi.

SOA è uno stile architetturale basato sul concetto di Servizio, che rappresenta quindi l'elemento strutturale su cui le applicazioni vengono sviluppate. Occorre quindi definire cosa si intende per servizio.

 

Servizi
Un servizio è, in prima analisi, una funzionalità di business realizzata tramite un componente che rispetta un'interfaccia. Ma qual'è la differenza tra applicazioni sviluppate a servizi rispetto a
quelle sviluppate seguendo "normali" paradigmi di programmazione distribuita o tecnologie già ampiamente utilizzate?
In passato, infatti, sono stati presentati spesso modelli di sviluppo incentrati su componenti con l'obiettivo del riuso. La finalità di di queste tecnologie è stata di cercare di creare un mercato di componenti per favorirne la diffusione. Questo tipo di politica ha in parte fallito soprattutto perchè i modelli di programmazione proposti hanno portato alla definizione di componenti la cui possibilità di utilizzo era limitata ad un certo ambito tecnologico. Dal punto di vista della logica funzionale che questi moduli dovrebbero implementare per essere commerciabili, questa deve essere sufficentemente complessa per giustificarne l'aquisto: spesso si è verificato che rispetto a prendere un componente prodotto esternamente, capirne l'interfaccia e adattarlo ai propri scopi e ai propri processi è preferibile svilupparsi il componente da zero.

Inoltre, mentre oggi è chiaro che la necessità di sistemi informativi complessi è quella di avere componenti in grado di comunicare tra loro in maniera eterogenea e disaccoppiata, le tecnologie orientate al "mercato dei componenti" hanno spesso dato più importanza alla possibilità di riconfigurare i moduli sviluppati per essere utilizzati su applicazioni diverse piuttosto che a sottolineare le possibilità di integrazione.

SOA parte dalle considerazioni che hanno portato al fallimento del riuso dei componenti in ambito enterprise e definisce una serie di proprietà che i servizi devono soddisfare per essere realmente riusabili e facilmente integrabili in ambiente eterogeneo:

  • I Servizi devono essere ricercabili e recuperabili dinamicamente.
    Chi necessita di un servizio deve essere in grado di ricercarlo sulla base dell'interfaccia e di chiamarlo a tempo di esecuzione. Questo tipo di meccanismo permette un forte disaccoppiamento tra chi richiede la funzionalità e chi la fornisce, permettendo inoltre di cambiare l'entità che esegue il servizio a tempo di esecuzione in maniera trasparente rispetto al chiamante.

  • I Servizi devono essere autocontenuti e modulari.
    Per essere realmente riusabili, è importante che i servizi non siano legati al contesto o allo stato di altri servizi. Ovviamente le applicazioni richiedenti necessitano di avere stato persistente tra le invocazioni ma questo deve essere separato dal fornitore di servizio. In pratica non dovrebbe esserci uno stato conversazionale nelle chiamate tra chi richiede il servizio e chi fornisce il servizio o, per usare una terminologia più precisa, i servizi dovrebbero essere stateless.

  • I Servizi devono definire delle interfacce esplicite e indipendenti dall'implementazione
    Deve essere possibile invocare servizi in maniera indipendente dal linguaggio e dalla piattaforma. Questo si può ottenere definendo delle interfacce che possono essere invocate tramite protocolli compresi da tutti.

  • I Servizi devono essere debolmente accoppiati (loosely coupled).
    L'accoppiamento si riferisce al numero di dipendenze tra i moduli. Ogni tipo di architettura ben definita è orientata ad avere accoppiamento debole, cioè un numero di dipendenze tra le entità basso e ben controllato. Un sistema formato da componenti fortemente accoppiati è più rigido e difficilmente modificabile.

  • I Servizi devono avere un'interfaccia distribuita e devono essere accessibili in maniera trasparente rispetto all'allocazione.
    Un servizio con un'interfaccia distribuita può essere pubblicato sulla rete, diventando così disponibile ai componenti che lo vogliano utilizzare. L'accesso tramite la rete permette inoltre di avere trasparenza rispetto alla reale allocazione del servizio.

  • I Servizi devono avere preferibilmente un'interfaccia a "grana grossa" (coarse-grained).
    Un servizio che corrisponda ad un'unica chiamata e un'unica esecuzione complessa ha in genere dei vantaggi rispetto a una serie di chiamate a tanti servizi più piccoli. In questo modo infatti vengono fatte meno chiamate remote (tipicamente poco efficienti), non c'è bisogno di trovare un sistema per mantenere lo stato tra più chiamate ed è più semplice gestire problematiche legate al fallimento della comunicazione remota. Comunque può essere sensato definire servizi "piccoli" soprattutto se questi servizi possono essere utilizzati per essere composti in altri servizi, infatti...

  • I Servizi devono essere componibili.
    Dal punto di vista SOA le applicazioni sono aggregazione di servizi. E' quindi importante disegnarne le interfacce in modo che corrispondano a funzioni di business riusabili, ovvero a servizi indipendenti e autocontenuti. La composizione di servizi per la produzione di applicazioni o di servizi più complessi viene indicata con il termine Service Orchestration.


Una architettura SOA è quindi una architettura software che definisce un modo di descrivere i componenti con caratteristiche ben specifiche orientate al riutilizzo e all'integrazione. E' importante notare che a livello implementativo la tecnologia utilizzata per lo sviluppo dei servizi non è determinante finchè vengono rispettate queste caratteristiche.

 

Ricerca e invocazione di servizi
Abbiamo detto che un servizio deve definire un'interfaccia pubblicabile sulla rete, ricercabile e invocabile in maniera indipendente dal linguaggio e dalla piattaforma.
Per ottenere questi requisiti, le applicazioni SOA definiscono dei ruoli:

  • Service Requester : l'entità che richiede il servizio; può essere un modulo di un'applicazione o un altro servizio.
  • Service Provider: l'entità che fornisce il servizio e che ne espone l'interfaccia.
  • Service Contract : definisce il formato per la richiesta di un servizio e della relativa risposta.
  • Service Broker : Direttorio in rete dei servizi consultabili.

Poichè i servizi devono essere ricercati e recuperati dinamicamente, il Service Contract deve essere pubblicato su un Service Broker dal Service Provider. Il Service Requester deve richiedere al Service Broker il Contract relativo al servizio richiesto, che utilizzerà per eseguire il servizio tramite un protocollo di trasporto.


Figura 1
- Ricerca e invocazione di servizi


Questo modello si può estendere con l'utilizzo di un Service Proxy, che non è altro che un'implementazione del pattern proxy [2] per i servizi. In questo caso il proxy può essere messo a
disposizione dal Service Provider per i Service Requester e può essere utile per nascondere l'operazione di ricerca del servizio e mantenere una cache dei risultati delle ricerche già fatte.
La comunicazione in questo caso è a carico del proxy, che può inoltre implementare dei meccanismi di failover-recovery. Ad esempio a seguito di un fallimento della comunicazione con un servizio, il Service Proxy può cercare un'altra entità che espone lo stesso servizio e chiederne l'esecuzione, tutto questo in maniera trasparente per il Service Requester.


Figura 2 - Service Proxy

Una volta che il Service Requester ha un riferimento al servizio che vuole utilizzare, come avviene la chiamata? Sia il requester che il provider devono utilizzare un protocollo di comunicazione che sia comprensibile per entrambi. Questo protocollo deve essere deciso sulla base dell'ambiente di utilizzo e dei requisiti in termini di efficienza e robustezza. Ad esempio nel caso di integrazione
spesso la soluzione più interessante è utilizzare protocolli di messaging asincrono [3].

Nulla vieta inoltre che un servizio possa supportare la possibilità di essere invocato tramite più protocolli (Multiprotocol Service Invocation). In linea di principio, un servizio potrebbe essere definito una sola volta tramite l'interfaccia e avere molte implementazioni che supportano diversi protocolli di accesso. In parole povere, se un servizio è "ordina una pizza", avere Multiprotocol Service Invocation equivale a avere la possibilità di ordinare una pizza tramite telefono, e-mail, telegramma, fax, ecc... Questo è importante in un ambiente in cui occorre fornire funzionalità a componenti che "parlano" lingue diverse.

 

SOA e Web Services
I concetti definiti da SOA non sono legati ad una tecnologia particolare, tuttavia i Web Services rappresentano un modo molto adatto e basato su standard di esporre servizi.

In questo tipo di implementazione le interfacce dei servizi sono definite tramite WSDL (Web Services Description Language) che possono essere pubblicate tramite UDDI (Universal Description Discovery and Integration). La comunicazione avviene normalmente tramite messaggi SOAP scambiati tramite HTTP. WSDL comunque supporta la possibilità di utilizzare anche altri protocolli di comunicazione permettendo quindi di avere Multiprotocol Service Invocation.

Riassumendo, il mapping tra le entità SOA definite e i WS è molto semplice:

 

Conclusioni
In questa breve presentazione abbiamo definito le caratteristiche che i servizi di un'applicazione SOA devono soddisfare. Si sono inoltre brevemente introdotti i Web Services come soluzione utile a sviluppare applicazioni service-oriented.
Nei prossimi articoli verranno presentate le tecnologie che rappresentano lo stato dell'arte dell'integrazione a servizi con Web Services in ambito J2EE e verranno proposti esempi pratici.

 

Bibliografia
[1] Booch, Rumbaugh, and Jacobson - "The UML Modeling Language User Guide", Addison-Wesley
[2] Gamma, Helm, Johnson, Vissides - "Design patterns : elements of reusable object-oriented software" , Addison-Wesley
[3] Hohope, Woolf - "Enterprise Integration Patterns", Addison-Wesley
[4] BEA su SOA: http://dev2dev.bea.com/technologies/soa/index.jsp
[5] IBM su SOA: http://www-106.ibm.com/developerworks/webservices/newto/
[6] Microsoft su SOA: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnmaj/html/aj2service.asp


MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it