|
L'idea nasce dal blog di Greg Wilkins, autore fin dal 1995 di software Open Source. È in quell'anno infatti che inizia lo sviluppo del server HTTP Jetty e del relativo Servlet Container. Ora Jetty è parte di CodeHaus (http://www.codehaus.org/). Greg ha contribuito inoltre a JBoss e ad Apache Geronimo. Come esperto di tecnologie Web e Servlet in particolare, ha voluto condividere le sue idee sull'evoluzione che dovrebbero avere le servlet, dopo la finalizzazione della versione corrente, la 2.5. Il problema scatenante è il nuovo modello di chiamata a "cometa", utilizzato dalla nuova generazione di applicazioni Web che utilizzano AJAX. In origine, infatti le applicazioni AJAX utilizzavano un modello di tipo "polling": il client, a intervalli regolari, inviava richieste al server allo scopo di mantenere aggiornata e/o validata l'interfaccia utente. Con lo stile a "cometa" il client apre una connessione HTTP, che viene lasciata aperta dal Web Server. In questo modo il server ha la possibilità di inviare informazioni al client in modalità push. In sostanza, si utilizzano connessioni HTTP long- lived, a lunga durata. Questo è un modo più efficiente di utilizzare le risorse, ma anche questo modello non è privo di problemi. L'analogia con la cometa risiede nel fatto che la prima richiesta può essere considerata come la testa di una cometa e la sua scia rappresenta il tempo in cui la connessione HTTP rimane aperta. Le novità proposteI casi d'uso che Greg profila, soprattuto in merito allo stile di programmazione a "cometa", sono i seguenti:
- input non bloccante. L'abilità di ricevere dati da un client senza bloccare l'esecuzione se i dati arrivano lentamente. Effettivamente, questo aspetto non è centrale per l'API asincrona, visto che la maggior parte delle richieste perviene in un singolo pacchetto. Inoltre la gestione può essere postposta fino all'arrivo del primo pacchetto contenente dati effettivi. L'obiettivo sarebbe comunque l'evoluzione delle API delle servlet verso applicazioni che non debbano implementare alcun input/output.
- output non bloccante. È la caratteristica di inviare dati al client senza bloccare l'esecuzione se il client o la rete sono lenti. Sebbene la necessità di output asincrono è molto maggiore rispetto alla necessità dell'input asincrono, Greg non ritiene neanche questo un elemento essenziale. Grandi buffer possono permettere al Servlet Container di inviare la maggior parte delle risposte in modo asincrono. Inoltre, per risposte di dimensioni ragguardevoli sarebbe meglio evitare del tutto che il codice dell'applicazione gestisca l'input/output.
- ritardare la gestione della richiesta. Lo stile "cometa" delle Web Application AJAX possono richiedere che la gestione di una richiesta venga ritardata fino a quando non avviene un timeout o un qualche tipo di evento. Il ritardare la risposta alle richieste è utile anche in quei casi in cui sia necessario recuperare una risorsa remota o lenta da caricare prima di poter servire la richiesta o in qui casi in cui sia necessario temporeggiare per evitare troppi accessi simultanei. Attualmente l'unico modo per supportare questo punto, e che sia anche conforme alle specifiche, è di attendere all'interno della servlet. Questo però comporta un consumo di risorse e di thread.
- ritardare la chiusura della risposta. Applicazioni Web AJAX che utilizzano lo stile cometa potrebbero richiedere che una risposta sia lasciata aperta per permettere l'invio di dati addizionali quando avviene un evento asincrono. Anche in questo caso, l'unico modo standard in cui si può fare ora è di attendere all'interno della servlet, consumando un thread e altre risorse.
- gestione del codice 100 (Continua). Un client potrebbe richiedere un handshake dal server prima di inviare il corpo della richiesta. Se questo viene inviata automaticamente dal contenitore diventa impossibile utilizzare il codice di ritorno 100. Se l'applicazione è in grado di decidere se inviare un codice 100, un'API asincrona potrebbe evitare che un thread venga consumato durante il ritorno al client.
Tutti questi casi possono essere riassunti come: "alcune volte è solo necessario fermarsi ad attendere qualcosa", sapendo che un'attesa all'interno del metodo Servlet.service() è costoso, per i seguenti motivi:
- è necessario un thread.
- Se l'input/output è iniziato sono necessari i relativi buffer.
- Se sono stati ottenuti i Reader/Writer, sono necessari i relativi converititori di caratteri.
- La sessione non può essere passivata.
- Tutto quanto allocato dalla catena dei filtri servlet deve essere mantenuto.
Le soluzioniAd oggi esistono alcune implementazioni che cercano di affrontare questo problema:
- Jetty ha il meccanismo della Continuazione, studiato per le applicazioni comet;
- BEA ha un meccanismo di risposte future;
- Glassfish ha un layer NIO estensibile per I/O asincrono al di sotto del modello delle servlet;
- Gli sviluppatori di Tomcat hanno appena iniziato lo sviluppo al supporto di applicazioni
comet. Greg rileva come la cosa ironica è che, mentre la versione 2.5 delle Servlet risolve moli problemi di portabilità, AJAX ne sta introducendo di nuovi. Ed effettivamente la versione 2.5 non ha portato molte novità, ma tante chiarificazioni orientate alla portabilità. AJAX pone delle nuove problematiche che il JCP dovrà affrontare. Non è ancora chiaro come si possa standardizzare una soluzione, ma Greg rileva cosa NON dovrebbe essere:
- una API su una servlet specifica. Nel momento in cui il Servlet Container ha identificato la specifica servlet da invocare, molte delle operazioni collegate sono state svolte. Inoltre, siccome i filtri e i dispatcher sono in grado di redirigere la richiesta, qualsiasi API asincrona strettamente legata a una servlet dovrebbe seguire lo stesso percorso.
- Basata sulla tecnologia Continuations di Jetty. Sebbene questa sia una utile astrazione è necessaria una soluzione più a basso livello in grado di offrire una maggiore efficienza e permettere ulteriori funzionalità.
- L'esposizione di canali o in generale API NIO al programmatore della servlet. Questi dettagli di implementazione dovrebbero essere nascosti all'utilizzatore; inoltre, in taluni casi si potrebbero impiegare tecnologie diverse da NIO.
La soluzione su cui sta lavorando Greg è diversa. Si basa su un oggetto coordinatore che può essere mappato a percorsi URL proprio come i filtri e le servlet. Il coordinatore dovrebbe essere richiamato dal contenitore in risposta a eventi asincroni e si dovrebbe occupare del coordinamento delle chiamate sincrone ai servizi. ConclusioniSe l'idea di Greg si dimostrerà rispondente alle nuove sfide che pone lo stile di programmazione a "cometa", ne verrà implementato un prototipo in Jetty 6, e da qui potrebbe passare al JCP, per essere standardizzato. Bibliografia[1] http://www.theserverside.com/news/thread.tss?thread_id=40560
[2] http://www.mortbay.com/MB/log/gregw/?permalink=asyncServlets.html
[3] http://www.codehaus.org/
[4] http://docs.codehaus.org/display/JETTY/Continuations
[5] http://blogs.pathf.com/agileajax/2006/05/comet_socket_hu.html
[6] http://alex.dojotoolkit.org/?p=545
[7] http://www.irishdev.com/NewsArticle.aspx?id=2166
|