
GO REACTIVE! Applicazione anni 2000 Decine di server Tempi di risposta nell’ordine dei secondi Ore di downtime per manutenzione Dati nell’ordine dei Gigabyte PRINCIPI DI Accedute da dispositivi desktop Applicazione moderne (≥ 2010) REACTIVE PROGRAMMING Cluster di migliaia di processi multicore INGEGNERIA DEL SOFTWARE Tempi di risposta nell’ordine dei millisec Università degli Studi di Padova Dipartimento di Matematica 100% uptime Corso di Laurea in Informatica, A.A. 2013 – 2014 Dati nell’ordine dei Petabyte 2 Accedute da qualsiasi tipo di dispositivo [email protected] Ingegneria del software mod. B Riccardo Cardin GO REACTIVE! REACTIVE MANIFESTO • Real-time, engaging, reach, • Nessun redesing per Nuovi requisiti richiedono nuove tecnologie collaborative ottenere la scalabilità • Nessuna latenza nelle Reactive Application • Scalabilità on-demand risposte Orientate agli eventi • Risk-management Scalabili "Readily responsive to a stimulus" responsive Resilienti Merriam-Webster Responsive react to events react to load scalable resilient La natura event-driven abilita La scalabilità non deve dipendere alle altre qualità da risorse condivise event-driven • Downtime è perdita di denaro react to failure react to users • Parte del design Sistemi resilienti permettono I tempi di risposta non devono • Loosely coupled design di recuperare errori a tutti dipendere dal carico di lavoro • Communication orientation i livelli 3 4 • Uso efficiente delle risorse Ingegneria del software mod. B Riccardo Cardin Ingegneria del software mod. B Riccardo Cardin MODELLO SINCRONO MODELLO SINCRONO Il mondo sincrono è senza futuro... Il mondo sincrono è senza futuro... // Synchronous world (w/o Future) Esempio: recuperare il nome del file più pesante val session = socialNetwork.createSessionFor("user", credentials) public String getBiggestFile(final File folder) { // blocked on method, waiting for results (latency)... session.getFriends() long maxLength = 0L; // There are a lot of operation to do!!! :( String fileName = null; for (final File fileEntry : folder.listFiles()) { Frequenti operazioni di I/O if (maxLength < fileEntry.length()) { // Not so efficient fileName = fileEntry.getName(); Scarso utilizzo delle feature offerte dai processori moderni maxLength = fileEntry.length(); } Larga diffusione delle architetture multiprocessore } Cicli non ottimizzati return fileName ; } Scarso parallelismo o gestione difficoltosa Java fileEntry.length() // I/O if (maxLength… // computation Tipico dei linguaggi imperativi e ad oggetti C, C++, Java, ... ... 5 6 Tempo totale di attesa CPU poco utilizzata, I/O sovrabbondante Ingegneria del software mod. B Riccardo Cardin Ingegneria del software mod. B Riccardo Cardin MODELLO ASINCRONO MODELLO ASINCRONO Callbacks Callbacks Funzioni da invocare al termine di una elaborazione CPU1 Gestione migliore della CPU Ridotti tempi di attesa CPU2 I/O è ancora presente, ma viene distribuito Più processi gestiscono più richieste CPU3 sull’elaborazione di più CPU Asynchronous JavaScript and XML (AJAX) CPU4 var callback = function(){ alert('I was called back asynchronously'); Tempo totale di attesa }; In attesa della risposta, è $.ajax({ Linguaggi o framework che gestiscano l’elaborazione type: 'GET', possibile continuare asincrona e concorrente url: 'http://example.com', l’elaborazione (rendering UI) done: callback, // positive case Node.js, jQuery, ... fail: anotherCallback // negative case 7 Ma...c’è sempre un ma... 8 }); jQuery Ingegneria del software mod. B Riccardo Cardin Ingegneria del software mod. B Riccardo Cardin module.exports = function (dir, cb) { fs.readdir(dir, function (er, files) { if (er) return cb(er) Difficile gestire le var counter = files.length eccezioni con blocchi MODELLO ASINCRONO var errored = false try/catch var stats = [] Callbacks...HELL!!! files.forEach(function (file, index) { fs.stat(path.join(dir,file), function (er, stat) { if (errored) return if (er) { errored = true Innesto callback per gestire return cb(er) i flussi degli eventi } stats[index] = stat if (--counter == 0) { var largest = stats .filter(function (stat) { return stat.isFile() }) .reduce(function (prev, next) { // [6] if (prev.size > next.size) return prev return next }) cb(null, files[stats.indexOf(largest)]) } }) // [1] Difficile da verificare }) // [2] 9 e manutenere 10 }) // [3] } node.js Ingegneria del software mod. B Riccardo Cardin Ingegneria del software mod. B Riccardo Cardin FUTURES E PROMISES FUTURES E PROMISES Futures Monad Tecnica per eseguire molte operazioni in parallelo, in Rappresenta un contesto di esecuzione (framework) modo efficiente e non-blocking Amplificatore di tipi, computation builder Stile dichiarativo Può racchiudere un tipo Immutabile public class Monad<T> { Rappresenta un segnaposto per un risultato futuro public Monad(T t) { /* ... */ } } Componibili È componibile con altre monadi Implementano meccanismi per la gestione delle eccezioni Composizione (a.k.a. concatenazione) sul tipo racchiuso // With Futures (asynchronous world) val session = socialNetwork.createSessionFor("user", credentials) public class Monad<T> { // Create placeholder for computation public abstract <V> Monad<V> bind(Function<T, Monad<V>> f); } val f: Future[List[Friend]] = future { session.getFriends() } // Statements here can be executed, while waiting for results :) Spesso permette di estrarre il valore del tipo contenuto scala 11 12 Caratteristica dei linguaggi funzionali Ingegneria del software mod. B Riccardo Cardin Ingegneria del software mod. B Riccardo Cardin FUTURES E PROMISES FUTURES E PROMISES Monad Future[T] è una monad È simile ad una bolla! Può racciudere Racchiudono l’elaborazione da eseguire in modo qualcosa asincrono (callback) È qualcosa di Successfully completed / Failed with an exception non concreto Eventual execution: nessun vincolo temporale import scala.util.{Success, Failure} // Asynchronous execution inside future context val f: Future[List[String]] = future { Può session.getRecentPosts evaporare, } è il risulato lasciando // Do something else... posts libero il f onComplete { dell’elaborazione // onSuccess contenuto case Success(posts) => for (post <- posts) println(post) // onFailure case Failure(t) => println("An error has occured: " + Può ricevere istruzioni su 13 t.getMessage) 14 } cosa fare del contenuto t è un’eccezione scala Ingegneria del software mod. B Riccardo Cardin Ingegneria del software mod. B Riccardo Cardin FUTURES E PROMISES FUTURES E PROMISES Valore che rappresenta l’elaborazione Future[T] è una monad Promise[T] Composizione funzionale di più elaborazioni Single-assigment container (monad) / proxy Non più callback hell!!! Un Future legge il risultato di un’elaborazione asincrona Si riporta il modello asincrono al modello sincrono Una Promise scrive (completa) un Future Se un future nella catena fallisce, fallisce l’intera catena val p = promise[T] scala // Future that is completed by the promise // First future execution val f = p.future val rateQuote = future { val consumer = future { connection.getCurrentValue(USD) startDoingSomething() } f onSuccess { // Bind second execution to first case r => doSomethingWithResult() r val purchase = rateQuote map { quote => } if (isProfitable(quote)) connection.buy(amount, quote) } produceSomething else throw new Exception("not profitable") val producer = future { } val r = produceSomething() startDoingSomething // Get final result p success r // Promise completes the Future purchase onSuccess { // It should be ‘p failure exception’ also 15 doSomethingWithResult 16 case _ => println("Purchased " + amount + " USD") continueDoingSomethingUnrelated() } scala } Ingegneria del software mod. B Riccardo Cardin Ingegneria del software mod. B Riccardo Cardin FUTURES E PROMISES FUTURES E PROMISES Javascript promises (Q library) Java 8 promises: CompletableFuture<T> Promise e future sono fusi nelle medesime strutture A Future that may be explicitly completed (setting its value promiseMeSomething() and status), and may include dependent functions and actions // value is the return value of promiseMeSomething .then(function (value) { that trigger upon its completion. Javadoc // Do something as soon as promiseMeSomething finishes }, // Something went wrong, reason is an exception then ritona una Creazione (usando le lambda extension) function (reason) { }); promise, quindi è final CompletableFuture<String> future = Effettua l’override del concatenabile CompletableFuture .supplyAsync(() -> { metodo Promise stile Scala Q Deferreds //...long running... CompletableFuture.get() return "42" ; var deferred = Q.defer(); }, executor); FS.readFile("foo.txt", "utf-8", function (error, text) { thenApply è simile a map if (error) { deferred.reject(new Error(error)); } Composizione (future stile Scala) di Scala else { deferred.resolve(text); } // f1 is a promise that will completed with an Integer value }); permette di CompletableFuture<Double> f3 = return deferred.promise; Deferred 17 18 completare una promise. f1.thenApply(Integer::parseInt).thenApply(r -> r * r * Math.PI). exceptionally(ex -> "We have a problem: " + ex.getMessage()); concatenabile Ingegneria del software mod. B Riccardo Cardin Ingegneria del software mod. B Riccardo Cardin REACTIVE EXTENSIONS (RX) REACTIVE EXTENSIONS (RX) Gestione sequenze di valori in modo asincrono Observables (RxJava) Observable sequences Event Iterable (pull) Observable (push) Single items Multiple items Retrieve data T next() onNext(T) T getData()
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages8 Page
-
File Size-