Nel primo Code Snippet abbiamo visto all'opera Microsoft Visual Studio 2010 per la creazione di un semplice progetto; abbiamo poi eseguito in locale il progetto nel simulatore di Windows Azure denominato Windows Azure Compute Emulator ovvero l'ambiente che simula il comportamento e fornisce le API del sistema operativo Windows Azure.
In questo snippet cercheremo di capirne meglio il funzionamento e la sua interazione con Visual Studio 2010.
Ripartiamo dal progetto di esempio che abbiamo creato nello snippet precedente per eseguirlo in ambiente locale: il nostro progetto per ora contiene solo una pagina e, rispetto al template di default proposto da Visual Studio, presenta una label che abbiamo valorizzato con l'orario corrente. Utilizziamo questo esempio come base da arricchire con nuove funzionalità.
Nota: occorre aprire Visual Studio con un account amministrativo per rendere possibile l'interazione fra l'IDE e il Windows Azure Compute Emulator (fino alla versione 1.2 dell'SDK l'ambiente locale era denominato Development Fabric).
La prima modifica che faremo è incrementare il numero delle istanze (per default è 1), aprendo la configurazione del Web Role all'interno del progetto Windows Azure: è sufficiente un doppio click sul progetto evidenziato nell'immagine seguente:
Aperta la maschera di configurazione del progetto cloud (doppio click sul progetto evidenziato nell'immagine), inseriamo 5 nel valore delle istanze come nella figura seguente.
Premendo F5
, come abbiamo visto, Visual Studio contatta l'ambiente di simulazione locale e invoca il deploy dell'applicazione stessa: l'applicazione è composta dal risultato della compilazione, zippata in un file con estenzione .cspkgs
, e dal file di configurazione che descrive all'ambiente (reale o simulato) le nostre richieste. Nel nostro caso stiamo chiedendo all'ambiente di creare 5 istanze Small e di configurare di conseguenza il load balancer per gestire il bilanciamento delle richieste fra di esse.
Eseguendo l'applicazione, il risultato su un browser è identico a quanto avremmo ottenuto lasciando inalterato il numero di instanze:
L'ambiente espone sulla porta 81 (IIS occupa la 80) e, correttamente, risponde alla nostra richiesta. La differenza rispetto ad avere una sola instanza si nota dietro le quinte all'interno del Windows Azure Compute Emulator che, infatti, presenta ben 5 finestre di tracing al posto di una sola:
Ogni finestra presenta le informazioni di tracing di ogni istanza di Web Role per ogni deployment attivo. Il numero 73
che vediamo nella sezione di sinistra è un numero progressivo assegnato dall'ambiente ad ogni deployment. Il 73
si trova anche all'interno del file system in quanto ogni deployment viene effettuato in una directory separata dal precedente.
In pratica l'ambiente, ad ogni operazione di deploy, crea una directory apposita e installa l'applicazione e le sue componenti all'interno di tale directory. È importante sottolineare che se vogliamo eseguire unit test oppure semplicemente controllare le operazioni effettuate dall'applicazione sulla directory corrente, è fondamentale controllare il numero di deployment per rintracciare la directory corretta sul file system.
Ogni istanza viene poi "installata" in sottodirectory differenti per simulare il comportamento di Windows Azure che utilizza macchine virtuali diverse per ogni istanza.
Ad esempio:
C:UsersRobertobAppDataLocaldftmps0deployment(73)resdeployment(73).DevLeap.AzureBookManager.DevLeap.AzureBookManager.FrontEnd.0
Rappresenta la mia directory locale dove l'emulatore ha effettuato il deploy della prima instanza (l'instanza zero) dell'applicazione.
Il Windows Azure Computer Emulator utilizza inoltre più processi per simulare il comportamento delle diverse istanze come si può notare dal Task Manager cercando i processi WaIISHost.exe
.
Nel caso utilizziate ancora la versione 1.2 dell'SDK i processi avevano un diverso nome: WaWebHost.exe
. La modifica sul nome del processo non è puramente formale: nella versione 1.3 dell'SDK è stata introdotta la modalità Full IIS con cui è possibile far girare le applicazioni cloud all'interno del processo di IIS.
Le modifiche effettuate nell'IDE sul progetto Windows Azure Web Role vengono registrate in due file fondamentali per l'infrastruttura: i file ServiceDefinition.csdef e ServiceConfiguration.cscfg contengono infatti il modello che descrive le modalità operative, fra cui il numero delle istanze e la loro tipologia, necessarie a Windows Azure per fornirci le componenti della piattaforma di cui abbiamo bisogno.
Il file ServiceConfiguration.cscfg si presenta così:
<?xml version="1.0" encoding="utf-8"?>
<ServiceConfiguration serviceName="DevLeap.AzureBookManager"
xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration"
osFamily="1" osVersion="*">
<Role name="DevLeap.AzureBookManager.FrontEnd">
<Instances count="5" />
<ConfigurationSettings>
<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString"
value="UseDevelopmentStorage=true" />
</ConfigurationSettings>
</Role>
</ServiceConfiguration>
A parte la prima riga, il tag ServiceConfiguration indica che l'applicazione gira su qualunque versione di Windows Azure e indica all'infrastruttura stessa che desideriamo che siano effettuati aggiornamenti automatici (osVersion="*"
).
Le impostazioni all'interno del Role che descrive il front-end contengono il numero delle istanze che abbiamo appena visto all'opera nell'ambiente locale e un settaggio che riguarda la diagnostica: ne parleremo nei prossimi snippet.
Lo spazio su disco
Proviamo a richiedere al sistema operativo qualche megabyte di spazio disco: vi ricordo che le risorse fisiche non sono direttamente accessibili in Windows Azure; non possiamo quindi scrivere su C:
o su D:
in quanto non sappiamo ne dove ne come è stato installato il sistema operativo sulla macchina su cui verrà effettuato il deploy della nostra applicazione: è il bello di Windows Azure!
Ad esempio, richiedendo una macchina Small potremmo "finire" su un server che ha un disco C
oppure se richiediamo una macchina ExtraLarge (visto che otteniamo un I/O superiore) potremmo finire su una macchina che ospita su C
il sistema operativo e su D
un disco apposito per i dati, oppure potrebbe esserci una SAN con un disco mappato sulla lettera X
.
Ogni risorsa deve essere quindi utilizzata tramite le API di Windows Azure che mappano le risorse fisiche nelle risorse logiche che possiamo utilizzare dalla nostra applicazione. Ad esempio dovremmo chiedere a Windows Azure una quantità di spazio disco all'interno del modello che descrive la nostra applicazione e utilizzare poi alcune API per domandare a Windows Azure stesso dove ha allocato lo spazio richiesto. Queste due operazioni che sembrano complesse, ma, come stiamo per vedere sono in realtà banali, chiudono il nostro secondo code snippet.
Per prima cosa "chiediamo lo spazio disco". Dalla maschera di configurazione del nostro Web Role, andiamo sul tab Local Storage e richiediamo uno spazio di 50 MB denominato MyStorage
.
Il nome è importante in quanto dovrà essere fornito alle API per capire dove è stato allocato lo spazio per, appunto MyStorage
.
Il file di definizione dell'applicazione si modifica di conseguenza:
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="DevLeap.AzureBookManager"
xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WebRole name="DevLeap.AzureBookManager.FrontEnd">
<Sites>
<Site name="Web">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="Endpoint1" protocol="http" port="80" />
</Endpoints>
<Imports>
<Import moduleName="Diagnostics" />
</Imports>
<LocalResources>
<LocalStorage name="MyStorage" cleanOnRoleRecycle="false" sizeInMB="50" />
</LocalResources>
</WebRole>
</ServiceDefinition>
La prima parte, rimasta immutata, descrive gli endpoint, ovvero i punti tramite i quali è possibile raggiungere l'applicazione: il default prevede un solo endpoint che risponde sulla porta 80.
Aggiungiamo una label alla pagina di default per visualizzare il path assegnatoci da Windows Azure:
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="DevLeap.AzureBookManager.FrontEnd._Default" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<h2>Welcome to DevLeap Azure Book Manager</h2>
<p>L'ora corrente nel cloud è <asp:Label ID="lblTime" runat="server" /></p>
<p>Il nostro spazio su disco è sotto <asp:Label ID="lblStorage" runat="server" /></p>
</asp:Content>
E poi dal codice del metodo PreRender
valorizziamo tale label utilizzando la classe RoleEnviroment
.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.WindowsAzure.ServiceRuntime;
namespace DevLeap.AzureBookManager.FrontEnd
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_PreRender(object sender, EventArgs e)
{
lblTime.Text = DateTime.Now.ToString();
lblStorage.Text = RoleEnvironment.GetLocalResource("MyStorage").RootPath;
}
}
}
Si possono fare due prove:
- Lanciare l'applicazione per vedere il path su disco dove l'ambiente di simulazione locale ha deciso di creare lo spazio richiesto
- Aprite una seconda finestra di browser copiando l'indirizzo della richiesta: è molto probabile che notiate una directory diversa in quanto il load balancer ha rediretto la richiesta di "un secondo" browser su un'altra istanza, dimostrando come, anche nell'ambiente locale, le istanze siano separate come processo e spazio disco
Da questo semplice esempio emerge una considerazione importante: NON usare MAI il Local Storage per appoggiare dati applicativi poiché non è condiviso alle varie instanze. Il Local Storage serve solo per fare caching o appoggiare momentaneamente dati che devono poter essere ricalcolati. Il Local Storage equivale al disco fisso del Web Server e come tale NON DEVE essere usato per dati applicativi che DEVONO invece essere memorizzati centralmente: vedremo fra un paio di snippet il Windows Azure Storage Account.
Prima di terminare la lezione, provate a mettere un breakpoint su una delle righe del metodo PreRender e poi, fate F5: si, avete pensato bene, si può debuggare in locale e... dalla versione 1.3 dell'SDK potremmo anche effettuare una sessione di debug live sull'applicazione una volta messa in deploy sul cloud.