Nel secondo articolo della guida, dedicato a .NET abbiamo creato insieme un semplice progetto Windows Azure e, nel terzo articolo, lo abbiamo testato nel simulatore locale per poi pubblicarlo sul cloud tramite gli strumenti offerti da Visual Studio.
In questo articolo ci occupiamo dell'accesso allo Storage Account, lo spazio che possiamo "riservare" su Windows Azure per memorizzare in modo centralizzato blob, entità in tabelle, messaggi in coda o dischi virtuali. Questo spazio non deve essere confuso con SQL Azure, che, rappresenta un altro componente della piattaforma che espone il mondo relazionale di SQL Server sul cloud.
Lo storage account è, come indica il nome, uno spazio di memorizzazione legato alla nostra subscription, che, in perfetto stile Windows Azure si paga a consumo calcolando il solo spazio occupato e il numero di transazioni effettuato su di esso.
In pratica ci viene messo a disposizione uno spazio di 100 TB (avete letto bene), affidabile e sempre disponibile in quanto ogni dato memorizzato viene replicatosu 3 macchine diverse, ad alte performance in quanto in caso di necessità i dati vengono suddivisi su macchine diverse per eseguire query parallele, accessibile da qualunque piattaforma via REST/HTTP, per il quale a fine mese ci viene presentato un conto che tiene in considerazione solo lo spazio effettivamente occupato e il numero di accessi effettuati ad esso.
Tutto il resto è trasparente per lo sviluppatore che, tramite alcune librerie disponibili per .NET, Node.js, PHP, Java, ma anche per piattaforme mobile come Windows Phone, iPhone, Android, può scrivere poche e semplici righe di codice per gestire i propri dati. Ovviamente occorre computare anche la banda utilizzata al download dei dati come per qualunque altro componente Windows Azure.
Sono previste alcune subscription gratuite che forniscono per un periodo di tempo limitato, ad esempio 500MB di blob (o dati in tabelle o messaggi in coda) sullo Storage Account senza pagare un centesimo e testare la nostra applicazione effettuando 10.000 operazioni gratuite sullo storage al mese. L'obiettivo è fornire agli sviluppatori la piattaforma gratuitamente per poter testare le feature dei servizi esposti.
Come per la parte "computazionale", solo se sforiamo i limiti indicati nella subscrition, incorreremo in una fattura a fine mese. Vi invito anche a controllare i prezzi per capire il costo effettivo: al momento della scrittura di questo articolo, lo storage account viene calcolato a 0,0887
Euro per GB allocato e a 0,0071
per ogni 10.000
transazione nell'arco del mese.
Lo Storage Account è accessbile via REST/HTTP: lo storage, in pratica, non solo è accessibile (previa verifica di sicurezza sugli accessi) da qualunque tipologia di client, ma anche accessibile da ovunque. Non occorre infatti avere una applicazione ospitata su Windows Azure per poter accedere allo storage. Durante la creazione dello storage account riceviamo l'url relativo che verrà esposto pubblicamente e reso di fatto accessibile da qualunque location sul pianeta con una connessione internet.
Dal portale di Windows Azure, occorre selezionare la voce Storage Account, scegliere la subscription sulla quale legare lo storage account per poi fornire un nome univoco all'account.
Il nome dello storage account deve essere univoco in quanto viene utilizzato come prefisso per l'URI di accesso. Ad esempio scegliendo "devleap", verrà creato in automatico sul DNS un dominio devleap.blob.core.windows.net
che ci consentirà di effettuare richieste REST di inserimento, modifica, cancellazione e query per file binari, devleap.table.core,windows.net per gestire entità in tabelle e devleap.queue.core.windows.net per creare code e gestirne i relativi messaggi.
Come si può notare dall'immagine, la sezione Hosted Services, Storage Accounts & CDN propone nel menu in alto la voce Hosted Service per la gestione della parte computazionale (le istanze per le applicazioni) e una sezione Storage Account, oggetto di questo articolo.
La maschera centrale ci propone, per ogni subscription (Windows Azure Cloud Essential è ad esempio una delle mie due subscription free legate a questo account Windows Live), l'elenco degli Storage Account esistenti e i dettagli su ciascuno di essi nella maschera delle Properties a destra.
Come si nota, per l'account "devleap" vengono riportati gli URI accennati precedentemente, la location dove è stato creato lo storage account e una coppia di chiavi (Primary e Secondary) che consente di firmare le richieste di accesso allo storage in modo da proteggere il tutto da accessi indesiderati.
Per creare un nuovo storage account è sufficiente utilizzare il pulsante "New Storage Account" e compilare le informazioni a maschera seguente:
È possibile scegliere la regione dove creare lo storage account oppure creare un affinity group ovvero un gruppo di affinità per servizi che verranno tenuti all'interno dello stesso data center: su Windows Azure è impossibile conoscere la location fisica delle macchine che ospitano i nostri servizi come testimonia l'immagine precedente; non troviamo "Data Center X, Via xyz, Tel: xxxx", ma semplicemente l'indicazione della regione in cui possono essere presenti, ovviamente, più data center.
Inserendo due diversi servizi in West Europe non è detto che siano ospitati fisicamente nello stesso data center: un affinity group garantise invece che più servizi vivano nella stessa location fisica abbattendo la latenza dello scambio dei dati e i costi in quanto il traffico intra-datacenter non si paga.
Tramite il pulsate "View" è possibile visualizzare e fare un copia/incolla della chiave di accesso, che, insieme al nome dello storage account ci servirà per effettuare le richieste dalla nostra applicazione. Visual Studio, nel designer della configurazione cloud, ci propone un tipo di impostazione denominata Connection String in cui inserire queste informazioni:
Come si nota, la prima opzione disponibile, ci svela che esiste un emulatore dello storage locale che ci consente di testare una applicazione in locale anche per quanto rigurda la memorizzazione dei dati.
L'applicazione può creare un contenitore di blob all'interno dello storage account, ovvero una sorta di directory per organizzare al meglio i blob all'interno dello storage account; questa operazione, in una applicazione web può essere effettuata dal classico metodo Application_Start:
// Recupera informazioni account da "cloud" config
// CloudStorageAccount account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
// Recupera informazioni da .config classico
CloudStorageAccount account = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["DataConnectionString"]);
// Crea wrapper per client
CloudBlobClient blobClient = account.CreateCloudBlobClient();
// Ottiene un riferimento al container
CloudBlobContainer container = blobClient.GetContainerReference("gallery");
// Creazione container
// N.B. La CreateIfNotExist esegue comunque la richiesta HTTP
container.CreateIfNotExist();
// Imposta permesso di accesso
BlobContainerPermissions permissions = container.GetPermissions();
permissions.PublicAccess = BlobContainerPublicAccessType.Container;
container.SetPermissions(permissions);
La prima riga di codice recupera le informazioni sullo storage account dalla configurazione del progetto cloud e la memorizza in una classe che consente poi di accedere alle diverse tipologie di risorse ospitabili nello storage. Il codice commentato consente di vedere le differenze fra l'utilizzo della configurazione cloud rispetto all'utilizzo della stessa stringa di connessione inserite nel classico file di configurazione .NET.
La seconda riga di codice crea la classe CloudBlobClient a partire dallo storage account che consente di lavorare con gli oggetti di tipo blob, e, la terza riga imposta il contenitore dove andremo a lavorare su "gallery". Da notare che fino alla riga di codice successiva, non è stato effettuato nessun accesso allo storage account.
Le ultime tre righe di codice, ovviamente opzionali, consentono di impostare l'accesso pubblico al container: nel nostro esempio inseriremo una immagine nel container e consentiremo un accesso HTTP/REST senza credenziali per la lettura delle immagini contenute; un container pubblico consente l'accesso libero in lettura ai blob, ma protegge i dati in scrittura.
Per testare l'accesso, possiamo usare una semplice pagina ASP.NET che proponga in una griglia i blob esistenti e un classico file upload per inserire nuovi blob:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebRole1._Default" %>
<%@ Import Namespace="Microsoft.WindowsAzure.StorageClient" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:FileUpload ID="FileUpload" runat="server" />
<asp:Button ID="btnUpload" runat="server" OnClick="btnUpload_Click" Text="Upload" />
<br />
<asp:GridView ID="gridBlob" runat="server" />
<br />
</div>
</form>
</body>
</html>
Il codice del metodo PrePrender
popola la griglia con i blob esistenti nel container:
// Repera info su Storage Account da .cscfg
CloudStorageAccount account = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["DataConnectionString"]);
// Crea wrapper per client
CloudBlobClient blobClient = account.CreateCloudBlobClient();
// Ottiene un riferimento al container
CloudBlobContainer container = blobClient.GetContainerReference("gallery");
// Binding tradizionale
gridBlob.DataSource = container.ListBlobs().Select((b) => b.Uri.AbsoluteUri);
gridBlob.DataBind();
Il codice è identico nella prima parte rispetto a quanto inserito nel metodo Application_Start; segue poi la chiamata al metodo ListBlobs, che, come si può notare consente anche espressioni LINQ.
Inseririamo il codice dietro al pulsante di upload per effettuare l'inserimento di un nuovo blob all'interno dello storage:
CloudStorageAccount account = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["DataConnectionString"]);
CloudBlobClient blobClient = account.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("gallery");
// Ottiene reference al Blob
CloudBlob blob = container.GetBlobReference(FileUpload.FileName);
// Esegue upload
blob.UploadFromStream(FileUpload.FileContent);
Il metodo UploadFromStream consente di inviare il blob partendo dallo stream ricevuto dal classico componente ASP.NET di upload.
Visto che abbiamo creato un container che consente l'accesso pubblico è possibile utilizzare direttamente gli URI proposti per scaricare le immagini:
Ad esempio utilizzando questo URI:
https://devleap.blob.core.windows.net/gallery/1-medium.jpg
(da notare l'accesso HTTPS) si ottiene questo risultato:
Nel prossimo articolo vedremo all'opera lo storage account per la memorizzazione di entità applicative.