CARATTERISTICHE SALIENTI DELLO STANDARD JMS
Transcript
CARATTERISTICHE SALIENTI DELLO STANDARD JMS
0000223986 Andrea Ceruti Reti di calcolatori LS Sviluppo di un’infrastruttura di supporto per aste in tempo reale tramite l’utilizzo di un middleware orientato ai messaggi. Abstract Questa relazione documenta il lavoro svolto per il corso di Reti di calcolatori LS e intende riassumere le scelte che hanno guidato la realizzazione di un’infrastruttura di supporto per aste in tempo reale. Il progetto è nato dal desiderio di approfondire le caratteristiche di un Message Oriented Middleware e si propone di analizzare le possibilità offerte dai MOM nella realizzazione di applicazioni che beneficino del disaccoppiamento tra le parti offerto da infrastrutture a messaggi. L’ infrastruttura sviluppata è una piattaforma di compravendita utilizzabile dalle case d’asta per realizzare vendite online in diretta. L’idea è nata dal desiderio di simulare il funzionamento della piattaforma LIVE AUCTION di Ebay e dal sogno di poter occupare in futuro un piccolo posto nello spazio competitivo che si libererà quando la società americana chiuderà il servizio, ritenuto marginale in termini di fatturato. Il presente lavoro si è prefisso l’obiettivo di realizzare un’ architettura affidabile che garantisca efficienza, disponibilità e tolleranza ai guasti, requisiti indispensabili per questo tipo di applicazione. Introduzione Il progetto è stato realizzato utilizzando le API di Java Message Service (JMS) e sfruttando le funzionalità messe a disposizione dal Message Oriented Middleware (MOM) ActiveMQ, un middleware open source che supporta le specifiche 1.1 di JMS. Un middleware cooperativo è un componente software che si posiziona in un’architettura di rete tra lo strato di trasporto e quello di applicazione per facilitare l’elaborazione cooperativa: viene richiamato dall’applicazione in fase esecutiva e sgrava l’applicazione da pesanti compiti di gestione non strettamente legati alle sue funzionalità operative specifiche. Questo strato software funge da intermediario tra le diverse applicazioni, fornendo ad esse un’interfaccia standard per usufruire dei propri servizi. Ogni applicazione che usufruisce di un middleware può dunque essere sviluppata senza preoccuparsi dei dettagli della comunicazione. Un Message Oriented Middleware è una tecnologia di middleware che permette la comunicazione con scambio di messaggi tra due o più applicazioni. Le applicazioni non interagiscono direttamente tra di loro in quanto il mittente ed il destinatario dell’informazione non devono necessariamente essere a conoscenza l’uno dell’altro: è il MOM che riceve i messaggi dal produttore dell’informazione e li recapita ai relativi consumatori dopo opportune trasformazioni. La caratteristica più rilevante di un middleware orientato ai messaggi risiede dunque nella possibilità di asincronicità della comunicazione, permettendo il disaccoppiamento spaziale e temporale fra i comunicanti: mittente e ricevente per comunicare non devono necessariamente essere disponibili allo stesso tempo (comunicazione distribuita debolmente accoppiata). I messagging system supportano due modelli di base per la gestione dei messaggi: PointTo-Point e Publish/Subscribe. Nel modello Point-To-Point il produttore invia messagi a una particolare coda (Queue) e un consumatore legge i messagi da questa coda. In questo modello il produttore conosce la destinazione dei messagi e invia i messagi direttamente alla coda del consumatore. • Quando un mittente invia un messaggio a una Queue, essa lo consegna solo al primo destinatario che cerca di ricevere un messaggio da quella Queue. Se nessun destinatario è attivo per la Queue nel momento in cui un mittente invia un messaggio, questo viene conservato dal Middleware finché non si attiva un destinatario (o finché non scade il time-to-live del messaggio, se questo è stato impostato). • Ogni messaggio è ritenuto ricevuto (acknowledged) quando un consumatore lo ha recuperato. Il modello Publish/Subscribe supporta la pubblicazione di messaggi in un particolare Topic. In questo modello, nè il publisher nè il subscriber sono a conoscenza l’ uno dell’ altro. • Più consumatori possono ricevere il messaggio. Il modello consente quindi una comunicazione uno-a-molti e si adatta bene in tutte quelle situazioni in cui è imprecisato il numero delle entità che interagiscono nel sistema. • C’è dipendenza temporale tra publisher e subscriber. Il publisher deve creare una subscription affinche i subscriber possano registrarsi. Un subscriber che si è sottoscritto ad un topic potrà consumare solamente messaggi pubblicati dopo la sua sottoscrizione. Il subscriber deve rimanere contemporaneamente attivo per ricevere i messaggi, a meno che non abbia stabilito una durable subscription. In tal caso, i messagi pubblicati mentre il subscriber non è connesso vengono ricevuti quando questo si riconnette. JMS – generalità JMS è un insieme di API che consentono lo scambio di messaggi tra applicazoni Java distribuite nella rete. In sostanza JMS fornisce un metodo standard tramite il quale le applicazioni possono creare, inviare e ricevere i messaggi usando un message oriented middleware. Un sistema architettato con JMS è costituito dai seguenti elementi: • Client JMS: programma in linguaggio Java che invia o riceve messaggi JMS. • Messaggio: raggruppamento di dati che viene inviato da un client a un altro. • JMS Provider: sistema di messaggistica che implementa la specifica JMS e realizza funzionalità aggiuntive per l’ amministrazione e il controllo della comunicazione attraverso messaggi. • Administered objects: sono oggetti preconfigurati da un amministratore ad uso dei client. Incapsulano la logica specifica del JMS provider nascondendola ai client, garantendo maggiore portabilita al sistema complessivo. Fanno parte del middleware lato server e sono usati dai client per inizializzare la comunicazione. • ConnectionFactory : è un administered object utilizzato da un client per realizzare la connessione con il provider. • Destination (queue/topic): è un administered object che svolge il ruolo di “deposito” in cui i mittenti possono lasciare i messaggi che creano, e da cui i destinatari possono recuperare i messaggi. Le destinazioni possono essere usate contemporaneamente da più mittenti e da più destinatari. A seconda del tipo di destinazione usato (queue o topic), la consegna dei messaggi avviene secondo modalità diverse (point to point o publish/subscribe). Le applicazioni JMS hanno qualità intrinseche che sono sintetizzabili in: • Asincronicità della comunicazione : il provider JMS consegna i messaggi al client appena quest’ ultimo si è reso disponibile. Il provider li consegna senza che il receiver abbia effettuato una richiesta specifica. • Affidabilità della comunicazione: JMS può assicurare che un messagio sia consegnato una ed una sola volta. • Disaccopiamento spaziale: grazie all’uso del sistema di naming di Java (JNDI) non è necessario avere un riferimento diretto ad oggetti remoti, ma ci si affiderà alla presenza degli administered object: la creazione di connection factory e destination è compito dell’ amministratore JMS che deve inserirli all’interno di un contesto JNDI in un opportuno namespace in modo che possano essere recuperati da qualsiasi client mediante le API JNDI • Quality of Service configurabile: le API JMS prevedono differenti livelli di affidabilità per considerare molteplici scenari applicativi. • Robustezza ai cambiamenti: sono presenti tipologie differenti di messaggi e features personalizzabili. Obiettivi dell’applicazione Il progetto ha come obiettivo quello di ricostruire una sala virtuale distribuita sul web, mediante una piattaforma che consenta di partecipare in diretta ad un’asta via internet. A questo scopo è necessario che un’ applicazione svolga il ruolo di battitore dell’ asta: le vendite devono essere gestite secondo un ordine prefissato accedendo ad un database dove sono memorizzati i lotti dei vari cataloghi e occorre notificare gli offerenti sulle informazioni che riguardano il lotto corrente. Gli acquirenti, come è facile intuire, devono poter accedere al servizio ed effettuare offerte sui lotti in tempo reale. Il battitore dunque è un produttore di informazione che interagisce con gli offerenti secondo una modalità di tipo push, ossia fornisce ai partecipanti informazioni riguardo i lotti oggetto dell’ asta (ad esempio prezzo di base e descrizione), senza che questi ne abbiano fatto esplicita richiesta; allo stesso tempo riceve dagli offerenti informazioni riguardo le loro offerte, quali ad esempio valore dell’offerta e identificativo dell’offerente. Pertanto sia battitore che offerenti sono entrambi produttori e consumatori di informazione, con l’unica differenza che il battitore deve produrre e fornire informazioni ad un numero di client non noto a priori e potenzialmente enorme. Un’ applicazione di questo tipo, caratterizzata da una comunicazione uno a molti di tipo push-based con un numero imprecisato di client, si presta bene ad essere realizzata utilizzando la tecnologia dei Java Message Serivce. Le api di JMS permettono infatti di accedere ed utlizzare i servizi dei sistemi di messaggistica, che supportano il modello publish/subscribe, adatto ad una comunicazione di tipo uno a molti. In base a questo paradigma, quando un messaggio viene inserito in una destinazione di tipo topic, può essere inviato a tutti i destinatari che si sono dichiarati interessati a riceverlo effettuando una sottoscrizione: i messaggi vengono inviati in broadcast ai consumer ed è il JMS provider che realizza l’operazione di dispatching dei messaggi a tutti i client. Ciascuno di essi riceverà una copia identica del messaggio inviato al topic. La tecnologia dei Java Message Service dunque si dimostra utile ai fini dell’ implementazione di un’ architettura efficace perchè supporta una comunicazione di tipo uno a molti, caratteristica intrinseca del sistema. Inoltre fornisce un supporto per la consegna affidabile e garantita dei messaggi, consentendo di implementare una soluzione robusta. Architettura logica del sistema Sono due le categorie di utilizzatori del sistema: • Il battitore (Admin) • Gli offerenti (Bidder) L’ applicazione Admin consiste di un’ interfaccia tramite la quale è possibile aprire i lotti in ordine sequenziale. L’ apertura di un lotto corrisponde alla pubblicazione in un topic di un messaggio contenente informazioni sul lotto in questione. I bidder dopo aver effettuato una sottoscrizione durevole a questo topic ricevono da esso le informazioni sui lotti e a loro volta pubblicano i messaggi corrispondenti alle loro offerte. Il nucleo centrale del sistema è dunque composto da un topic in cui l’ Admin è publisher di un messaggio chiamato Status contenente le informazioni sui lotti correnti e i bidder sono i subscriber interessati a ricevere questo messaggio. A loro volta i bidder sono publisher di un messaggio chiamato Bid contenente informazioni sulle offerte effettuate e l’ Admin è il subscriber interessato a ricevere questo messaggio. Struttura dei messaggi Entrambe le applicazioni Bidder e Admin creano degli oggetti TextMessage che incapsulano un documento XML come stringa Java. L’azione di offerta da parte del bidder viene pertanto notificata nel topic con un messaggio XML avente la seguente struttura: <LiveAuctionMessage> <Action> Bid </Action> <BidderName> Andrea </BidderName> <LotId> 1 </LotId> <Base> 200 </Base> <Price> 250 </Price> <Title> moneta romana 2 secolo a.c. </Title> </LiveAuctionMessage> L’ Admin aggiorna lo stato ogni qual volta apre un lotto nuovo o quando viene pubblicato nel topic un messaggio di offerta da parte di un bidder. Il messaggio XML con cui viene notificato nel topic l’ aggiornamento dello stato ha la seguente struttura: <LiveAuctionMessage> <Action> Status </Action> <CurrentLot> 1 </CurrentLot> <Base> 200 </Base> <Title> moneta romana 2 secolo a.c. </Title> <CurrentPrice> 250 </CurrentPrice> <CurrentWinner> Andrea </CurrentWinner> </LiveAuctionMessage> Pubblicazione dei messaggi Dal momento che le applicazioni coinvolte necessitano di “filtrare” i messaggi pubblicati nel topic (Status o Bid), si è deciso di utilizzare un’importante proprietà della tecnologia JMS: i message selector. Grazie a questa proprietà il consumatore specifica a quali messaggi è interessato e il provider JMS invia selettivamente solo quei messaggi ai client. Utilizzando i message selector dunque l’ onere di filtrare i messaggi è assegnato al provider JMS piuttosto che all’ applicazione client. Ciò ha il duplice vantaggio di ottimizzare il traffico di rete (riducendo il numero di messaggi da inviare ad un determinato ascoltatore), e di migliorare il codice applicativo permettendo di implementare consumatori più specifici. I message selector in sostanza sono stringhe contenenti un’ espressione che utilizza la logica booleana per stabilire quali messaggi debbano essere consegnati ai consumatori. A livello applicativo un message selector viene specificato sia in fase di invio del messaggio che in fase di creazione del consumatore. Nel nostro caso al momento della creazione del messaggio viene aggiunta ad esso una string property di tipo ACTION, il cui valore, settato tramite il metodo setStringProperty a ‘bid’ o ‘status’, identifica l’applicazione interessata alla ricezione del messaggio stesso. Dal lato subscriber, al momento della creazione di una sottoscrizione durevole, il metodo createDurableSubscriber permette di specificare come argomento, non solo il nome del topic e della sottoscrizione, ma anche il valore del selector: solo i messaggi con property corrispondente al valore del selector argomento di questo metodo vengono consegnati dal provider JMS. I message selector usano l’header e i property fields di un messaggio JMS come criteri in espressioni condizionali: il risparmio della banda del canale che si ottiene utilizzando i message selector va dunque a scapito delle performance del sistema, in quanto header e propeties del messaggio devono essere ricavati e successivamente paragonati dal provider JMS. Data l’alta frequenza delle operazioni di offerta dei bidder e di aggiornamento dello stato, si è preferito comunque utilizzare i message selector per evitare un eccessivo traffico di rete ed un superfluo trattamento di messaggi da parte di applicazioni non interessate alla ricezione di tutti i messaggi. Si è deciso inoltre di ottimizzare la sessione scegliendo la modalità di “message acknowledgement” AUTO_ACKNOWLEDGE. Questa modalità realizza la politica della consegna dei messaggi once-and-only-once: si può cosi ridurre il traffico di rete rispetto alle altre modalità che realizzano semantiche atleast-once, a scapito però di un overhead sul server JMS che deve attuare questa politica. Il subscriber infatti definisce un message listener, ovvero una classe che implementa l'interfaccia javax.jms.MessageListener e ridefinisce il metodo onMessage(). Ogni qualvolta un messaggio arriva alla destinazione d'interesse, è il provider JMS che provvede ad invocare in maniera asincrona il metodo di callback onMessage(), alla cui esecuzione la sessione riconosce automaticamente il messaggio. All interno del metodo onMessage() viene invocato un parser xml il cui compito è quello di estrarre dai messaggi di interesse le informazioni da visualizzare nell’ interfaccia grafica. L’ implementazione del subscriber, e quindi del metodo onMessage(), è perciò concettualmente simile sia per il bidder che per l’ admin: ciò che cambia tra le due tipologie di client è l’implementazione del parser xml che deve analizzare due messaggi , ossia due stringhe xml diverse. Guaranteed Message Delivery Per aumentare il grado di reliability ed efficienza dell’ infrastruttura si sfrutta un'importante caratteristica offerta dai sistemi MOM, il Guaranteed Message Delivery che garantisce la consegna del messaggio, anche in caso di problemi al sistema. Un eventuale crash o failure del server porterebbe ad un’ indesiderata perdita di informazioni, inaccettabile per un’ applicazione in cui i messaggi rappresentano transazioni economiche. È per questo motivo che i messaggi possono essere resi persistenti (ad es: mediante JDBC) prima di essere recapitati ai consumatori. A questo scopo è necessario in fase di pubblicazione settare il Delivery Mode del messaggio a PERSISTENT. Si può impostare la modalità delivery sul singolo messaggio mediante parametro nel metodo publish(): publish(<message>, DeliveryMode.PERSISTENT, <priority level>, <expiration time>); Entrambi i messaggi Bid e Status sono stati resi persistenti per assicurare che non vengano persi in caso si verifichi un errore nel provider JMS; è lo stesso provider JMS che si occupa di memorizzare opportunamente i messaggi. Si è deciso inoltre di rendere le sottoscrizioni durevoli, in modo da consentire la ricezione dei messaggi anche se il client non era in ascolto al momento della generazione del messaggio. Le durable subscrpition rendono persistenti i subscriber: l’identificazione univoca del subscriber consente infatti, in caso di crash del JMS provider e successivo riavvio, di effettuare il resume del subscriber nello stato in cui era stato lasciato precedentemente, riprendendo la ricezione dei messaggi. Per questo motivo si è deciso di rendere durevole non solo la sottoscrizione al topic dei bidder, ma anche quella dell’ Admin. L’ utilizzo delle durable subscription si dimostra uile non solo in situazioni di recovery da guasti, ma anche perchè consente ad un bidder di loggarsi al sistema ad asta avviata e ricevere ugualmente informazioni sul lotto corrente, anche se non era in ascolto al momento della generazione del messaggio da parte dell’ Admin. Se infatti una sottoscrizione “durable” non ha subscriber attivi al momento, il JMS provider memorizza tutti i messaggi finché un subscriber non si attiva e i messaggi vengono ricevuti. La sottoscrizione persistente dura dall’istante di tempo in cui viene creata fino all’istante in cui viene cancellata con il comando topicSession.unsubscribe(). Si definisce l’identità unica di un subscriber stabilendo: • Un client ID per la connessione. • Un topic e un nome della sottoscrizione per il subscriber. Nel caso dei bidder si è settato l’ID dei bidder al valore corrispondente al numero IP della macchina sui cui si è loggato l’ offerente; il settaggio viene impostato tramite il metodo setClientId(String) di JMS applicato a un oggetto di tipo TopicConnection. ActiveMQ 1. Persistenza Se da un lato JMS offre la possibilità di specificare l’esatta Quality of Service di ogni scambio di messaggi in termini di guaranteed delivery e di consegna tramite semantica once-and-only-once, ActiveMQ mette a disposizione altre funzionalità per ottenere affidabilità del sistema, high availability e tolleranza ai guasti. ActiveMQ è un message broker open source che supporta le specifiche JMS 1.1. Un broker è la parte di una soluzione JMS lato server che si occupa di routing, recovery, persistenza e cosi’ via. Per quanto riguarda la persistenza, come detto precedentemente il provider JMS memorizza i messaggi su un persistent storage se il delivery mode è stato settato a persistent, di modo che sopravvivano a un riavvio del broker. Inoltre per sopperire alla mancanza del servizio e permetterne la successiva riattivazione, il provider JMS memorizza anche le durable subscriptions: se così non fosse il message server, in caso di fallimento, non sarebbe capace di consegnare i messaggi ai durable subscribers stessi. Per effettuare le operazioni di recovery il provider JMS: • ricrea le destinazioni • recupera la lista di “durable subscriptions” per ogni topic • recupera la lista dei messaggi • recupera la lista di acknowledge per ogni messaggio È possibile configurare ActiveMQ perchè gestisca la persistenza tramite file (AMQ message store) o tramite database esterno al provider JMS. È stata scelta quest ultima opzione perche ha come vantaggio un più facile recupero e interpretazione dei dati rispetto al caso in cui si utilizzi l’ AMQ message store, un sistema di gestione della persistenza basato su file utilizzato di default da ActiveMQ.. Le operazioni di accesso e scrittura su un DB sono sicuramente più pesanti dal punto di vista computazionale, ma questo approccio è sensato perchè la nostra applicazione non ha requisiti particolari di high performance. All’ avvio il broker creerà automaticamente due tabelle, ACTIVEMQ_ACKS e ACTIVEMQ_MSGS: la prima tabella mantiene in memoria informazioni relative ai subscribers e informazioni relative ai messaggi acknowledged, la seconda contiene al suo interno informazioni relative ai messsaggi. 2. High Availability e fault tolerance Le funzionalità finora introdotte non sono sufficienti qualora al sistema vengano richieste anche caratteristiche di affidabilità ed alta disponibilità. Nonostante siano stati resi persistenti i messaggi e siano state create sottoscrizioni durevoli, il provider JMS rappresenta un punto critico per l’ applicazione in quanto un suo eventuale crash non garantisce la continuità del servizio: in tal eventualità bisogna aspettare un suo riavvio prima che i messaggi possano essere consegnati nuovamente. ActiveMQ nella versione 5.1 mette a disposizione una funzionalità master/slave per garantire alta disponibilita e tolleranza ai guasti: l’ idea che guida questa funzionalità è che i messaggi vengano replicati su dei broker slave di modo che, in caso di failure hardware sulla macchina del master, si abbia immediato failover sullo slave senza perdita di messaggi. Utilizzando un database condiviso e JDBC come connettore è possibile adottare una configurazione master/slave eseguendo tanti broker quanti si ritengono opportuni, come mostrato nel seguente diagramma. Se il master perde la connessione al database o perde il lock esclusivo allora termina immediatamente l’esecuzione. Quando il master termina l’ esecuzione o fallisce, uno degli altri slave s’impadronisce del lock. I client perdono la connessione al master che si è fermato e il transport failover cerca di riconnetterli ai broker disponibili, uno dei quali diventa il nuovo master. Quando si riavvia il broker che aveva fallito questo riparte come slave, aspettando di impadronirsi del lock per diventare il master. In sostanza uno slave fornisce un broker hot stand by che sarà sempre sincronizzato, pronto a prendere posto se il master s’interrompe in seguito ad hardware failure. Per la nostra applicazione si è scelto di utilizzare un cluster di due broker per ottenere affidabilita e contenere i costi del sistema. Per configurare il cluster è sufficiente modificare i file di configurazione activemq.xml in ciascuna macchina del cluster come segue: <persistenceAdapter> <jdbcPersistenceAdapter dataSource="#mysql-ds"/> </persistenceAdapter> in modo da istruire i broker ad usare unicamente JDBC come data source. I client utilizzano il layer di trasporto Failover di ActiveMQ per collegarsi a uno dei broker : la sintassi di configurazione del Transport Failover permette di specificare un qualsiasi numero di URI. Il layer di trasporto failover sceglie casualmente uno degli URI e cerca di stabilire una connesione con esso: se ciò non avviene o se la connessione fallisce, una nuova connessione viene stabilita con uno degli altri URI. Dunque i client utilizzano la seguente stringa per connettersi ai broker disponibili: failover:(tcp://broker1:61616,tcp://broker2) dove broker1 e broker2 sono i nomi o gli indirizzi IP delle macchine su cui vogliamo eseguire i broker. 3. Clustered JDBC Lo svantaggio di una configurazione dei broker JDBC master/slave, come evidenzia il diagramma precedente, risiede nel fatto che si fa affidamento su un database come unico sistema di gestione della persistenza, e si ha pertanto un singolo punto di fallimento: in caso di hardware failure nella macchina su cui gira il database si perderebbero tutti i messaggi. Per evitare questo inconveniente nella nostra applicazione si sfrutta il concetto di RAIDb, Redundant Array of Inexpensive Databases. Uno degli obiettivi di RAIDb è quello di fornire a basso costo tolleranza ai guasti e prestazioni migliori di quelle di un singolo database, combinando molteplici istanze di database in una matrice di database. RAIDb-1 è una replica completa del database su ogni nodo del cluster e consente di accedere in maniera trasparente ad un cluster di db con l’astrazione di un unico db. Nonostante una replica competa vada a discapito di un rallentamento nelle operazioni di scrittura (UPDATE, INSERT, DELETE), si è deciso comunque di effettuare questa scelta, considerato che l’ applicazione non effettua scritture su db, se non nei casi in cui il provider JMS scrive nelle tabelle ACTIVEMQ_ACKS e ACTIVEMQ_MSGS. Anche se ciò può effettivamente avvenire con una frequenza elevata a seconda del numero di messaggi nel topic, le prestazioni non subiscono un degradamento significativo, dal momento che si è ritenuto sufficiente un numero di due backends per garantire affidabilità per cui le scritture devono essere trasmesse solo a due nodi. Per ottenere una configurazione RAIDb-1, si è deciso di utilizzare una tecnologia Java open source: Sequoia 2.10.10. Sequoia è un middleware open source che permette a qualsiasi applicativo di accedere in maniera trasparente ad un cluster di database tramite JDBC. Il driver Sequoia è un generico driver JDBC che sostituisce il driver JDBC specifico utilizzato dal client. Il driver Sequoia inoltra le interrogazioni SQL attraverso RMI al controllore Sequoia e ne riceve i corrispondenti risultati. Il client deve solo conoscere su quale nodo gira il controllore ed il nome del database virtuale cui accedere. Grazie a Sequoia si può settare la persistenza nel file XML di ogni broker facendo riferimento a un singolo database astratto con il seguente codice: <persistenceAdapter> <jdbcPersistenceAdapter dataSource="#sequoia-ds" /> </persistenceAdapter> <!-- Sequoia DataSource --> <bean id="sequoia-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="org.continuent.sequoia.driver.Driver"/> <property name="url" value="jdbc:sequoia://host1/activemq?relaxAutoCommit=true"/> ... </bean> Il database utilizzato viene chiamato activemq perchè di default ActiveMQ crea le tabelle ACTIVEMQ_ACKS e ACTIVEMQ_MSGS all interno di questo database; esso è solamente un’astrazione di un database in quanto fa riferimento a due backend reali posti su due macchine diverse (activemqDb1 e activemqDb2). Per ottenere questa astrazione è sufficiente modificare il file XML usato dal controllore Sequoia (controller.xml) con la seguente stringa, in maniera analoga per ogni nodo: <DatabaseBackend name=”node1” driver="org.gjt.mm.mysql.Driver" url=”jdbc:mysql://localhost/activemqDb1” connectionTestStatement=”select 1”> È necessario settare in questo file username e password usati da MySql per accedere al db su ciascun nodo e impostare il nome del database vrtuale con username e password per accedervi. All’ interno del db activemq sono state inserite anche la tabella auth_table, contenente i campi bidderName (chiave primaria) e bidderPassword, e la tabella lots contenente i campi lotId (chiave primaria), titolo e prezzo. Servizio di login Il nucleo centrale del servizio di login è costituito da due code unidirezionali, loginQueue e confirmQueue, e da due attori, ovvero il bidder che si vuole autenticare e un servizio autenticatore lato server. Similmente al caso del topic anche per il servizio di login le applicazioni conivolte ricevono i messaggi dalle destinazioni in modo asincrono. All’ atto del login il bidder invia nella loginQueue un messaggio chiamato LogIn, cioèun oggetto TextMessage che incapsula come stringa Java un documento XML di questo tipo: <LiveAuctionMessage> <Action> LogIn </Action> <BidderName> Andrea </BidderName> <BidderPassword> xxxxx </BidderPassword> </LiveAuctionMessage> Dal lato server deve essere attivo un servizio di autenticazione che implementa una classe receiver: alla ricezione del messaggio di LogIn nella loginQueue in maniera asincrona vengono estratti i dati di login dal messaggio e confrontati con quelli memorizzati nella tabella auth_table (dove si suppone siano memorizzati i dati degli utenti che si sono precedentemente registrati all’ asta via e-mail). Il servizio di autenticazione per ogni messaggio di LogIn inserito nella coda loginQueue invia nella confirmQueue un messaggio chiamato Confirm di questo tipo: <LiveAuctionMessage> <Action> Confirm </Action> <UserName> Andrea </UserName> <Token> true </Token> </LiveAuctionMessage> Analogamente il bidder, all’atto della ricezione di un messaggio di Confirm, legge il valore del token di tipo boolean e se questo corrisponde a true chiude il frame di login per aprire quello da cui il bidder puo partecipare all’ asta. Si è deciso di impostare un TimeToLive per il messaggi di LogIn e Confirm per evitare che, in caso il servizio di autenticazione non sia attivo a causa di una failure, rimangano messaggi inevasi nelle code. Packages e classi Il software è organizzato in quattro packages. Il package liveauction.common comune a tutte le applicazioni contiene classi di utilità generica come DBConnection che implementa i metodi per connettersi al database e leggerne i dati, e la classe XML_log che salva i messaggi su dei file XML, utilizzati per effettuare il parsing e come file di log per gli acquirenti e il battittore. I package liveauction.bidder e liveauction.admin realizzano le applicazioni bidder e admin e contengono classi che implementano la logica di pubblicazione nel topic, di sottoscrizione e ricezione dei messaggi da questo (PublisherLogic, Publisher, Subscriber). I package liveauction.bidder e liveauction.authenticator contengono anche le classi che implementano la logica di invio e ricezione dei messaggi nelle code (SenderLogic, Sender, Receiver). Le classi MessageService e ParserXML sono comuni a tutti i packages delle tre applicazioni. La classe MessageService costruisce i messaggi e li pubblica nei topic o li invia alle code. ParserXML provvede ad elaborare i documenti XML. per permetterne l’ estrazione dei dati d’ interesse. Conclusioni e sviluppi futuri L’ infrastruttura realizzata offre un sistema robusto e a basso costo per gestire aste in tempo reale. È stato realizzato un prototipo della piattaforma e, a causa della mancanza di una rete su cui poter lavorare, sono stati effettuati test solo su tre macchine organizzate con un cluster di due broker in configurazione master/slave, un cluster di due database replicati su due delle macchine disponibili, e quattro bidder loggati sulle tre macchine a disposizione ( tre di questi con clientId per la sottoscrizione al topic uguale al numero IP della macchina, e il quarto con clientID uguale a null). Sono stati simulati diversi scenari e possibili guasti e i risultati hanno dimostrato un buon grado di affidabilità e un ottimo funzionamento dell’ architettura progettata. Si è osservato un leggero ritardo (variabile, dell’ ordine di qualche secondo) nella connesione al database e quindi nell’apertura del primo lotto. Ciò èdovuto al fatto che si è scelto di utilizzaree come sistema di gestione della persistenza un database, rinunciando agli high perfourmance journal, ossia file utilizzati come storage da ActiveMQ aventi funzionalità simili a quelle di un database, ma piu performanti. Inoltre un’ organizzazione RAIDb-1 del database rallenta la connessione al db e le operazioni di scrittura, come osservato precedentemente. Questi inconvenienti non rappresentano un grave problema e non precludono il funzionamento dell’ infrastruttura, dal momento che comportano solo un ritardo nell’ apertura del primo lotto, per cui gli acquirenti semplicemente attenderanno pochi secondi prima dell’ inizo dell’ asta. Tuttavia si possono migliorare le perfomance se si hanno a disposizione file system di rete come i file system SAN (Storage Area Netwrks) che sono file system simultaneamente montati du diverse macchine. Utilizzando come sistema di gestione della persistenza file system di rete si possono migliorare nettamente le performance, dal momento che le operazioni su file sono sicuramente meno pesanti dal punto di vista computaziionale rispetto a quelle su db. In questo modo però si aumentano anche i costi del sistema, per cui la soluzione progettata rappresenta un buon compromesso tra performance e costi. Considerato che i messaggi rappresentano transazioni di denaro, è possibile inoltre rafforzare l’applicazione introducendo livelli di sicurezza sia all’ interno dei messaggi sotto forma di funzioni hash, sia per quanto riguarda il protocollo di comunicazione (ad esempio utilizzando SSL). Possibili miglioramenti possono riguardare anche il servizio di autenticazione che si può pensare di replicare per garantire disponibilità: nella soluzione proposta, in caso di caduta dell’ autenticatore, il client deve aspettare il riavvio del servizio e riprovare ad autenticarsi più tardi. Dal momento che l’applicazione admin nasce per affiancare un’asta in sala, si può far in modo che l’ admin possa aggiornare i prezzi provenienti dalla sala, cioè possa a sua volta fare offerte pubblicando a sua volta messaggi di Bid nel topic.
Documenti analoghi
PUBLISH/SUBSCRIBE: UTILIZZANDO IL JMS (JAVA MESSAGING
differenti possono richiedere una zona demilitarizzata del middleware per far sì che ognuna di esse
possa negoziare con tutte le altre applicazioni, spesso usando un fattore in comune (come i file ...