Azure, Azure…tutti ne parlano. Mi è venuta voglia di provarlo
Non mi metterò qui a rispiegare cos'è e come funziona. Tanto è già stato detto ed esistono diversi tutorials e video che ne spiegano i componenti.
Una cosa però vorrei riportare dal sito ufficiale a proposito dei servizi forniti per lo storage dei dati:
Simple data storage services
- Blobs, tables, and queues hosted in the cloud, close to your computation
- Authenticated access and triple replication to help keep your data safe
- Easy access to data with simple REST interfaces, available remotely and from the data center
Paura
REST??? Per accedere ai dati???
Tutte le volte che devo accedere al datastore devo usare http? E ricevere i dati in formato Atom, o simili? Mi stanno dicendo che non posso accedere ai dati con altri protocolli a più basso livello? E che se ho un’applicazione che usa ADO.NET non posso installarla su Windows Azure?
Un sospiro di sollievo
Imparo oggi (o mi sembra di capire) che SQL Data Services adesso si chiama SQL Azure, che supporterà ADO.NET e TDS e che sarà utilizzabile direttamente da Windows Azure. L’annuncio che SDS avrebbe supportato puri db relazionali (grazie a customer feedback) era di metà maggio, ma non avevo ancora trovato nessuna conferma che sarebbe stata possibile l’integrazione con Windows Azure. Questa è una buona notizia.
Non è ancora disponibile da provare però.
Test
Siccome non posso provare la parte con db relazionali, provo almeno TableStorage.
Scarico la CTP di Maggio e uno degli esempi che ci sono in rete per sporcarmi le mani e analizzare un po’ di numeri. L'esempio e' completo e mostra più e meno tutto: un Web Role con una ASP.NET web app + qualche servizio WCF, dati distribuiti su TableStorage e BlobStorage e anche l'utilizzo di Queues attraverso 2 istanze di Worker Roles. Quello che a me interessa però è molto semplice: capire la latency di quelle chiamate REST dal Web Role al Table Storage. In soldoni, quanto tempo ci vuole per recuperare dati dall’application layer.
Quindi, aggiungo una pagina al progetto, e faccio il deployment in the cloud - http://smartinzhs.cloudapp.net/LatencyTest.aspx (da qualche giorno il sito va a intermittenza…).
Il test interessante è “GetAll”.
Il codice è semplicissimo e si noti che calcolo solo il tempo effettivo per fare la chiamata. Quindi solo l’hop dal Web Role al TableStorage e ritorno – non tutto il round trip dal browser.
protected void btnGetAll_Click(object sender, EventArgs e)
{
var itemService = new ShortItemService();
Stopwatch sw = new Stopwatch();
sw.Start();
var items = itemService.RetrieveAllItems();
sw.Stop();
...
}
RetrieveAllItems() non fa altro che fare “select * from UserItems”.
Con i dati presenti, la dimensione media di un record è di 900Bytes (senza differenze estreme). Il numero di record totali nella tabella può oscillare nel tempo per come è stata disegnata l’applicazione che simula un sito di aste online. Quando eseguita in locale la query produce questa chiamata REST: “http://127.0.0.1:10002/devstoreaccount1/UserItems()” e ritorna una serie di entry come la seguente in format Atom:
<entryxml:base=http://127.0.0.1:10002/devstoreaccount1/ xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/"datetime'2009-06-23T19%3A36%3A52.517'"" xmlns="http://www.w3.org/2005/Atom">
<id>http://127.0.0.1:10002/devstoreaccount1/UserItems(PartitionKey='f1733617-df03-69b6-fae8-d1971a647c30',RowKey='1633813563221000000_8c216797-6e19-4770-9314-4704f3daef75')</id>
<title type="text"></title>
<updated>2009-07-07T01:44:13Z</updated>
<author>
<name />
</author>
<linkrel="edit" title="UserItems" href="UserItems(PartitionKey='f1733617-df03-69b6-fae8-d1971a647c30',RowKey='1633813563221000000_8c216797-6e19-4770-9314-4704f3daef75')" />
<category term="BidNow.UserItems" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:ItemId>8c216797-6e19-4770-9314-4704f3daef75</d:ItemId>
<d:Title>The Pragmatic Programmer</d:Title>
<d:ShortDescription>From Journeyman to Master</d:ShortDescription>
<d:EndDate m:type="Edm.DateTime">2009-06-23T12:18:42.1</d:EndDate>
<d:ThumbnailUrl>http://127.0.0.1:10000/devstoreaccount1/photos/thumbnails/8c216797-6e19-4770-9314-4704f3daef75.jpg?timeout=30</d:ThumbnailUrl>
<d:PhotoUrl>http://127.0.0.1:10000/devstoreaccount1/photos/8c216797-6e19-4770-9314-4704f3daef75.jpg?timeout=30</d:PhotoUrl>
<d:Timestamp m:type="Edm.DateTime">2009-06-23T19:36:52.517</d:Timestamp>
<d:PartitionKey>f1733617-df03-69b6-fae8-d1971a647c30</d:PartitionKey>
<d:RowKey>1633813563221000000_8c216797-6e19-4770-9314-4704f3daef75</d:RowKey>
</m:properties>
</content>
</entry>
Risultati
I numeri parlano da soli: 1.8secs per circa 80 records, con picchi fino a 2.3secs! Significa 2 secondi per estrarre 72KB dal data store!!! E la ciliegina: un record su db si aggira sui 900Bytes, on the wire diventa pi'u’ di 2KB a causa della format atom.
Inutile provare la stessa cosa con ADO.NET che usa TDS, sappiamo tutti che è mooolto più veloce e molto piu’ compatto; anche via TCP con client and db su macchine diverse.
Considerazioni
Di solito, si ha la percezione che un sito e’ veloce quando le richieste (o parte di esse) ci vengono servite sotto i 2 secondi in media (e sono stato largo). Secondo i dati di cui sopra, usando REST, Azure si mangia tutto il mio margine solo per accedere al db!
Ovvio il perché di REST per scenari dove è necessario accedere a dati “in the cloud” da ovunque, quindi l’unica opzione è HTTP. Posso vederne un utilizzo in termini di interoperabilita’. Ma nel caso di Windows Azure, dove application tier e dati sono entrambi in the cloud?
Per ora i dati ritornati dal TableStorage sono in semplice formato xml. Da quello che vedo con fiddler sui test in locale, il messaggio non è compresso e nulla viene fatto per minimizzarlo. Non ho idea se in the cloud il comportamento sia diverso…ma dubito, visto i tempi…
Se optassi per usare Table Storage con REST, dovrei progettare l’architettura diversamente da come la progetterei se avessi ADO.NET e TDS. Qui il problema non sta nel creare un livello di astrazione che mi renda trasparente il fatto che uso TableStorage invece di SqlServer (che non sarebbe neanche così difficile) ma piuttosto il fatto che il livello di chattiness accettabile per SqlServer, potrebbe non esserlo per TableStorage e viceversa, visto che i protocolli usati sono così differenti (tralasciamo l’integrazione di ORM).
Non riesco a pensare a tipiche applicazioni web (penso a SaaS per esempio), dove latency e responsivness sono requisiti critici, implementate utilizzando TableStorage e REST come stanno al momento. Tutt’altro discorso se si tratta di long running workflows.
Non c’e’ dubbio che la scalabilità sia garantita e se a ciò si aggiunge che tutti i problemi operativi in termini di infrastruttura diventano di Microsoft, la piattaforma è veramente interessante a patto che vadano bene i costi. Una volta che ci si orienta nel mare di nuovi termini l’esperienza per un developer non è neanche così male…una volta sviluppata l’applicazione questo è tutto ciò che si può fare in the cloud :)
Devo ricordare che Windows Azure (come anche SQLDataServices/SQLAzure) è ancora in CTP, quindi le cose cambieranno. Come? Chi lo sa… Cambieranno anche in termini di latency? I numeri adesso sono veramente poco incoraggianti. Spero nel supporto per accesso ai dati classico.
Sarei curioso di sapere se qualcun altro ha avuto altre esperienze e risultati diversi.