Esporta (0) Stampa
Espandi tutto

Procedure consigliate per la progettazione di servizi su larga scala nei servizi cloud di Azure

Aggiornamento: gennaio 2014

Autori: Mark Simms e Michael Thomassy

Collaboratori: Jason Roth e Ralph Squillace

Revisori: Brad Calder, Dennis Mulder, Mark Ozur, Nina Sarawgi, Marc Mercuri, Conor Cunningham, Peter Carlin, Stuart Ozer, Lara Rubbelke e Nicholas Dritsas.

Il cloud computing è un sistema di elaborazione distribuita. Per distribuire un'elaborazione è necessario valutare attentamente le operazioni di pianificazione e recapito, indipendentemente dalla scelta della piattaforma. Lo scopo di questo documento è fornire informazioni aggiuntive precise, basate su scenari reali dei clienti per compilare applicazioni scalabili in Azure e nel database SQL, utilizzando l'approccio Platform-as-a-Service (PaaS) in base al quale la piattaforma è considerata un servizio. Le applicazioni di questo tipo vengono compilate come servizi cloud di Azure mediante i ruoli Web e di lavoro.

ImportantImportante
NOTA: tutte le informazioni aggiuntive sulle procedure consigliate disponibili in questo documento derivano dall'impegno costante con i clienti che eseguono il codice di produzione in Azure. In questo documento viene illustrata la piattaforma (PaaS) di servizi cloud di Azure basata sulla versione 1.6 SDK. Le funzionalità quali Siti Web di Azure o Macchine virtuali di Azure (IaaS) non vengono descritte.

In questo documento vengono illustrati i concetti sulla progettazione sottostante per la compilazione di applicazioni Azure, funzionalità e limiti chiave della piattaforma Azure, nonché procedure consigliate per l'utilizzo dei servizi di base di Azure. L'attenzione viene concentrata sulle applicazioni riconducibili a un archivio dati distribuito in modo non molto coerente, in contrapposizione a modelli dati multi-tenant con coerenza assoluta o a densità elevata.

La modifica di aspetti delle applicazioni e dei servizi in uso in Azure può essere interessante per diversi motivi, ad esempio:

  • Conservazione o consolidamento di spese in conto capitale in spese operative (CapEx in OpEx).

  • Riduzione dei costi e miglioramento dell'efficienza grazie a una più stretta corrispondenza tra domanda e disponibilità dell'offerta.

  • Flessibilità e tempi di immissione sul mercato migliorati attraverso la riduzione o l'eliminazione delle barriere infrastrutturali.

  • Incremento dell'utilizzo di nuovi strumenti da parte degli utenti, ad esempio i dispositivi mobili.

  • Vantaggi garantiti dalla notevole scalabilità del cloud computing per compilare nuove applicazioni in grado di supportare un gruppo di destinatari globale in data center geograficamente distribuiti.

Vi sono numerosi validi motivi tecnici per sviluppare nuove applicazioni o eseguire il porting di alcune o di tutte le applicazioni esistenti in Azure. Dal momento che l'ambiente presenta numerose alternative di implementazione, è necessario esaminare con attenzione il modello di applicazione specifico per poter selezionare l'approccio di implementazione più appropriato. Alcune applicazioni sono ideali per i servizi cloud di Azure (approccio Platform-as-a-Service o PaaS), mentre altre possono trarre vantaggio da un approccio Infrastructure-as-a-Service (IaaS) parziale o completo, ad esempio le macchine virtuali di Azure. Infine, alcuni requisiti delle applicazioni potrebbero essere soddisfatti in modo ottimale utilizzando insieme entrambi i metodi.

L'applicazione in uso deve disporre di almeno uno dei tre aspetti chiave riportati di seguito per ottimizzare i vantaggi dei servizi cloud di Azure. Non deve necessariamente disporre di tutti questi requisiti. Infatti è possibile ottenere un rendimento alto del capitale investito applicando in modo ottimale uno soltanto dei seguenti aspetti in Azure. Tuttavia, un carico di lavoro che non presenta alcuna di queste caratteristiche, probabilmente non è ideale per i servizi cloud di Azure.

Gli aspetti importanti da valutare in un'applicazione sono:

  • Domanda elastica. Una delle proposte di valore chiave del passaggio a Azure è la scala elastica, vale a dire la possibilità di aggiungere o rimuovere capacità dall'applicazione (scalabilità orizzontale e scalabilità verticale) per meglio rispondere alla domanda dinamica dell'utente. Se la domanda del carico di lavoro è statica e costante, ad esempio un numero statico di utenti, di transazioni e così via, il vantaggio dei servizi cloud di Azure non viene ottimizzato.

  • Utenti e dispositivi distribuiti. L'esecuzione in Azure consente l'accesso immediato alla distribuzione globale delle applicazioni. Se il carico di lavoro dispone di una base utente vincolata in esecuzione in una singola ubicazione, ad esempio un unico ufficio, tramite la distribuzione cloud potrebbe non essere garantito il rendimento ottimale del capitale investito.

  • Carico di lavoro partizionabile. Nelle applicazioni cloud viene eseguita la scalabilità orizzontale e pertanto l'aggiunta di ulteriore capacità in blocchi più piccoli. Se l'applicazione dipende dalla scalabilità verticale, ad esempio database di grandi dimensioni e data warehouse, o è un carico di lavoro dedicato e specializzato, ad esempio un'archiviazione di grandi dimensioni, ad alta velocità unificata, deve essere scomposta (partizionata) per essere eseguita in servizi con scalabilità orizzontale affinché sia accettabile nel cloud. A seconda del carico di lavoro, questa operazione potrebbe essere non semplice.

Per riepilogare, quando si valuta l'applicazione, è possibile ottenere un elevato rendimento del capitale investito in spostamenti o compilazioni nei servizi cloud di Azure se il carico di lavoro presenta solo uno dei tre aspetti illustrati in precedenza che caratterizzano un ambiente PaaS come i servizi cloud di Azure. È probabile un ottimo rendimento del capitale investito da applicazioni che offrono tutte e tre le caratteristiche descritte.

Sebbene numerosi aspetti di progettazione delle applicazioni per Azure siano molto simili allo sviluppo locale, vi sono alcune differenze fondamentali circa il funzionamento della piattaforma e dei servizi sottostanti. Comprendere queste differenze, e di conseguenza la modalità di progettazione della piattaforma appropriata, è essenziale per offrire applicazioni in grado di garantire la scala elastica prevista nel cloud.

In questa sezione vengono descritti cinque principali concetti essenziali per la progettazione di compilazioni di applicazioni con scalabilità orizzontale distribuite su larga scala per ambienti PaaS come i servizi cloud di Azure. La comprensione di questi concetti consentirà di progettare e compilare applicazioni che non solo funzionano nei servizi cloud di Azure, ma che possono essere ulteriormente potenziate, restituendo tutti i vantaggi possibili relativamente agli investimenti effettuati. Tutte le considerazioni e le scelte relative alla progettazione descritte più avanti in questo documento saranno legate a uno di questi cinque concetti.

Inoltre, è opportuno notare che mentre molte di queste considerazioni e procedure consigliate vengono esaminate in termini di applicazione .NET, i concetti e gli approcci sottostanti non riguardano il linguaggio o la piattaforma.

Il cambiamento principale relativo allo spostamento da un'applicazione locale ai servizi cloud di Azure è correlato alla scalabilità delle applicazioni. Il metodo tradizionale per compilare applicazioni di grandi dimensioni si basa su una combinazione di scalabilità orizzontale (Web senza stato e server applicazioni) e di scalabilità verticale (acquisto di un sistema di memoria di grandi dimensioni/multicore più ampio, un server di database, compilazione di un data center più grande e così via). La scalabilità verticale non è un'opzione realistica nel cloud. L'unico modo per ottenere applicazioni effettivamente scalabili è progettare in modo esplicito per la scalabilità orizzontale.

Dal momento che molti degli elementi di un'applicazione locale rientrano già nella scalabilità orizzontale (server Web, server applicazioni), la sfida consiste nell'identificare quegli aspetti dell'applicazione che dipendono da un servizio con scalabilità verticale e nel convertirli, o eseguirne il mapping, in un'implementazione con scalabilità orizzontale. Il candidato principale a una dipendenza dalla scalabilità verticale è in genere il database relazionale (database SQL di Azure/SQL Server).

Nelle progettazioni relazionali tradizionali l'attenzione viene concentrata su un modello dati coerente a livello globale (scalabilità verticale a server singolo) con coerenza assoluta e comportamento transazionale. L'approccio tradizionale per fornire scalabilità in questo archivio di backup è stato quello di creare tutti gli elementi senza stato, rinviando la responsabilità di gestione dello stato all'istanza di SQL Server con scalabilità verticale.

Tuttavia, l'elevata scalabilità di SQL Server è caratterizzata da una chiara mancanza di una scala realmente elastica. Vale a dire, anziché usufruire della disponibilità di risorse estremamente valide, è invece necessario acquistare un server più grande, con conseguente fase di migrazione dispendiosa, la cui capacità supera decisamente la domanda e per il quale occorre ogni volta eseguire l'espansione con scalabilità verticale. Inoltre, quando si esegue successivamente la scalabilità dell'hardware di fascia media, si assisterà a una curva esponenziale dei costi.

Con il supporto architetturale garantito dalla scalabilità orizzontale dei servizi cloud di Azure, le applicazioni devono essere progettate per l'utilizzo di archivi dati con scalabilità orizzontale. Di conseguenza, si dovranno affrontare sfide come il partizionamento, in modo esplicito, dei dati in blocchi più piccoli, ognuno dei quali in grado di poter rientrare in una partizione dati o in un'unità con scalabilità orizzontale, e la gestione della coerenza tra gli elementi dati distribuiti. A tale scopo, eseguire la scalabilità tramite partizionamento in modo da evitare i numerosi svantaggi che caratterizzano la scalabilità verticale.

Basare la progettazione del cloud sulle note tecniche della scalabilità verticale, nonché sulla gestione dello stato e dei dati con scalabilità orizzontale rappresenta in genere la difficoltà più grande. La risoluzione di questi problemi e la progettazione di applicazioni in cui è possibile avvalersi delle funzionalità elastiche e scalabili dei servizi cloud di Azure e del database SQL di Azure per la gestione di dati durevoli saranno gli argomenti principali di discussione di questo documento.

Grazie a un livello di controllo quasi assoluto, accompagnato da un numero di scelte altrettanto illimitato, l'utente può attualmente gestire il proprio data center. Egli può infatti controllare ogni aspetto, dagli impianti fisici (aria condizionata, alimentazione elettrica, superficie), all'infrastruttura (rack, server, rete e così via) fino alla configurazione (topologia di routing, installazione del sistema operativo).

Questo livello di controllo comporta però costi operativi, di capitale, di risorse e di tempo. I costi di gestione di ogni dettaglio in un ambiente agile e in evoluzione sono il motivo della spinta verso la virtualizzazione e un aspetto chiave del cammino verso il cloud. La rinuncia al controllo assoluto è però compensata dalla riduzione dei costi di distribuzione e gestione e dalla maggiore flessibilità che queste piattaforme sono in grado di garantire. Il vincolo imposto da piattaforme di questo tipo è che le dimensioni (capacità, velocità effettiva e così via) dei componenti e dei servizi disponibili sono limitate a una gamma fissa di offerte.

Per fare un'analogia, si prenda in considerazione la spedizione commerciale di grandi quantità dove l'attività è basata principalmente sull'utilizzo di container. Questi container possono essere trasportati con vari mezzi (navi, treni e camion) e sono disponibili in diverse dimensioni standard, fino a una lunghezza di circa 16 metri. Se la quantità del carico da spedire supera la capacità del rimorchio più grande, è necessario adottare una delle soluzioni seguenti:

  • Utilizzo di più rimorchi. Questa soluzione comporta la suddivisione, o partizionamento, del carico in container diversi e il conseguente coordinamento del recapito dei rimorchi.

  • Utilizzo di un metodo speciale di trasporto. In caso di carichi non distribuibili in container standard perché troppo grandi, ingombranti e così via, devono essere adottate soluzioni altamente specializzate, ad esempio chiatte. Questi metodi sono in genere più costosi del trasporto merci standard.

Se si porta l'analogia in Azure, e nel cloud computing in generale, ogni risorsa presenta un limite. Sia essa una singola istanza del ruolo, un account di archiviazione, un servizio cloud o anche un data center, ciascuna risorsa disponibile in Azure presenta dei limiti finiti. Si può trattare di limiti di grandi dimensioni, ad esempio la quantità di spazio di archiviazione disponibile in un data center, paragonabile alle navi mercantili più grandi in grado di trasportare oltre 10.000 container, ma in ogni caso di limiti finiti.

Tenendo presente questo aspetto, l'approccio per eseguire la scalabilità consiste nel partizionare il carico e comporlo in più unità di scala, ad esempio più macchine virtuali, database, account di archiviazione, servizi cloud o data center.

Il termine unità di scala utilizzato in questo documento indica un gruppo di risorse (a) in grado di gestire un livello specificato di carico e (b) che possono essere combinate ai fini della gestione di carichi aggiuntivi. Ad esempio, le dimensioni massime di un account di archiviazione di Azure sono pari a 100 TB. Se è necessario archiviare più di 100 TB di dati, occorrerà utilizzare più account di archiviazione, vale a dire almeno due unità di scala di archiviazione.

Le linee guida generali per la progettazione della capacità di ogni servizio o componente di base di Azure verranno descritte nelle sezioni successive, insieme agli approcci consigliati per creare questi servizi utili per la scalabilità aggiuntiva.

Per compilare applicazioni locali altamente resilienti sono stati investiti tempo, energie e risorse umane ingenti. Questa attività si riduce in genere nel dividere l'applicazione in componenti con stato basso (server applicazioni, rete) e componenti con stato alto (database, reti SAN) e nel rendere ognuno di questi resiliente rispetto alle modalità di errore.

In questo contesto, il termine modalità di errore indica la seguente combinazione di fattori: (a) analisi del sistema in uno stato di errore che rappresenta la (b) conseguenza della causa dell'errore. Ad esempio, un database inaccessibile per un aggiornamento della password non configurato correttamente è una modalità di errore: lo stato di errore è l'impossibilità di effettuare la connessione (connessione rifiutata, credenziali non accettate) e la causa dell'errore è un aggiornamento della password non comunicato correttamente al codice dell'applicazione.

I componenti con stato basso garantiscono resilienza attraverso la ridondanza a regime di controllo libero ("loosely-coupled"), con relativa "integrazione" nel sistema gestito da sistemi esterni. Si inseriscano, ad esempio, server Web aggiuntivi dietro un bilanciamento del carico. Ogni server Web è identico agli altri (l'aggiunta di nuova capacità è una questione di duplicazione dell'immagine di un server Web di base), con integrazione nell'applicazione globale gestita dal bilanciamento del carico.

I componenti con stato alto garantiscono resilienza attraverso la ridondanza strettamente associata ("tightly coupled"), con l'integrazione perfettamente gestita tra i componenti. Di seguito vengono indicati alcuni esempi:

  • SQL Server. Per aggiungere un'istanza di SQL Server ridondante come parte di un cluster attivo/passivo è necessaria l'attenta selezione di hardware compatibile, vale a dire identico, nonché di archiviazione condivisa, ad esempio una rete SAN, per garantire il failover coerente transazionale tra più nodi.

  • Alimentazione elettrica. La fornitura di alimentazione elettrica ridondante rappresenta un esempio molto complesso, che richiede la concertazione di più sistemi per ridurre i problemi di carattere generale locali (più alimentazioni per un server, con hardware per passare da un impianto principale a uno ausiliario) e centrali (generatori di riserva in caso di perdita di potenza).

Gli approcci "tightly coupled" basati su soluzioni di resilienza sono intrinsecamente più costosi rispetto ad approcci "loosely-coupled" (aggiunta di più elementi duplicati) e richiedono personale altamente qualificato, hardware specializzato, nonché configurazione e testing oculati. Non solo sono difficili da capire, ma comportano anche costi notevoli per una corretta applicazione.

L'approccio incentrato sul garantire piattaforme hardware estremamente resilienti può essere considerato una sorta di "guscio d'uovo in titanio". Per proteggere il contenuto dell'uovo, si ricopre il guscio con uno strato di titanio resistente e costoso.

L'esecuzione di sistemi in scala (per ulteriori informazioni, vedere il documento disponibile all'indirizzo Web http://www.mvdirona.com/jrh/TalksAndPapers/JamesRH_Lisa.pdf) ha dimostrato che in un sistema sufficientemente ampio, ad esempio i sistemi di dati nella scala di Azure, la presenza di numerose parti mobili fisiche comporta l'inevitabile interruzione di alcune parti del sistema. La piattaforma Azure è stata progettata in modo da funzionare con questa limitazione, anziché contrastarla, facendo affidamento sul ripristino automatico da eventi di errore a livello di nodo. Questa finalità della progettazione caratterizza tutti i servizi di base di Azure ed è la chiave per progettare applicazioni in cui si utilizza il modello di disponibilità di Azure.

Il passaggio a Azure sposta l'attenzione del discorso sulla resilienza da sfida in termini di ridondanza dell'infrastruttura a sfida in termini di ridondanza dei servizi. Molti dei servizi di base che dominano la pianificazione della disponibilità locale continuano a funzionare in Azure:

  • Tramite il database SQL vengono gestite automaticamente più repliche coerenti dal punto di vista transazionale dei dati in uso. Gli errori a livello di nodo di un database vengono sottoposti automaticamente al failover nell'istanza secondaria coerente; si confronti la facilità di questo utilizzo con i tempi e i costi necessari per offrire resilienza locale.

  • Tramite il Servizio di archiviazione Azure vengono gestite automaticamente più copie coerenti dei dati. Per ulteriori informazioni, vedere il documento disponibile all'indirizzo Web http://sigops.org/sosp/sosp11/current/2011-Cascais/11-calder-online.pdf. Gli errori a livello di nodo di un volume di archiviazione vengono sottoposti automaticamente al failover in un'istanza secondaria coerente. Analogamente al database SQL, si confronti questo utilizzo completamente gestito con la gestione diretta dell'archiviazione resiliente in una rete SAN o in un cluster locale.

Tuttavia, in questa sezione vengono illustrati aspetti relativi alla disponibilità e non alla resilienza. La resilienza è solo una parte dei tanti vantaggi che gli utenti si aspettano, entro i limiti del contratto di servizio. Se tutti i componenti dell'infrastruttura di un servizio sono integri, ma il servizio non è in grado di far fronte ai volumi previsti degli utenti, esso risulta non disponibile, né potrà garantire i vantaggi che ci si aspetta.

I carichi di lavoro incentrati su applicazioni mobili o sociali, ad esempio applicazioni Web pubbliche con applicazioni per dispositivi mobili, tendono a essere più dinamici di quelli destinati a un pubblico vincolato e richiedono un approccio più complesso per la gestione di eventi burst e carichi massimi. I concetti chiave da tenere presente nella progettazione di applicazioni Azure caratterizzate dalla disponibilità vengono descritti in dettaglio in tutto il documento, in base a questi punti centrali:

  • Ogni servizio o componente di Azure fornisce un determinato contratto di servizio (SLA, Service Level Agreement), che non può essere direttamente correlato alla percentuale di disponibilità richiesta per l'esecuzione dell'applicazione. Comprendere gli aspetti di tutti i componenti del sistema, il relativo contratto di servizio sulla disponibilità e la modalità di interazione è essenziale per capire la disponibilità complessiva che si può garantire agli utenti.

    • Evitare singoli punti di errore che potrebbero inficiare il contratto di servizio, ad esempio ruoli a istanza singola.

    • Creare o eseguire il fallback su più componenti per ridurre l'impatto di un servizio specifico che risulta offline o non disponibile.

  • In ogni servizio o componente di Azure si può verificare un errore, sia esso temporaneo di breve durata o un evento di durata. È consigliabile scrivere l'applicazione in modo da gestire normalmente gli errori.

    • In caso di errori temporanei, fornire meccanismi di tentativi appropriati per una nuova connessione o una nuova esecuzione del lavoro.

    • Per altri eventi di errore, fornire strumenti avanzati per l'evento di errore (segnalazione dell'errore nelle operazioni) e un messaggio di errore appropriato all'utente.

    • Dove possibile, eseguire il fallback su un servizio differente o su un flusso di lavoro. Ad esempio, se una richiesta di inserimento dati nel database SQL non viene completata, per un motivo non temporaneo, ad esempio uno schema non valido, scrivere i dati nell'archiviazione BLOB in un formato serializzato. In questo modo sarà possibile acquisire i dati in modo duraturo e inoltrarli al database, una volta risolto il problema relativo allo schema.

  • Tutti i servizi saranno caratterizzati da una capacità massima, o in modo esplicito, tramite criteri di limitazione o asintoto del carico massimo, o in modo implicito, raggiungendo il limite di una risorsa di sistema.

    • Progettare l'applicazione in modo che, in caso di raggiungimento dei limiti delle risorse, il relativo funzionamento si riduca gradualmente consentendo di intraprendere l'azione appropriata per attenuare l'impatto sull'utente.

    • Implementare la funzionalità di logica di tentativi/backoff appropriata per evitare rallentamenti nei servizi. Senza un meccanismo di backoff adeguato, non si disporrà mai della possibilità di aggiornare i servizi a valle dopo un evento di massima attività, dal momento che tramite l'applicazione si tenterà continuamente l'inserimento di carico ulteriore nel servizio, attivando i criteri di limitazione o determinando la mancanza di risorse.

  • I servizi in cui si potrebbero riscontrare eventi burst rapidi devono poter garantire una gestione graduale del superamento del relativo carico massimo di progettazione, in genere tramite funzionalità di contenimento.

    • Progettare i servizi in modo da separare quelli meno importanti durante eventi di carico eccessivo, come avviene con il rallentamento del flusso di sangue negli arti quando esposti a temperature estremamente basse.

    • Il corollario che ne deriva è che non tutti i servizi forniti dall'applicazione sono caratterizzati dallo stesso livello di criticità aziendale e possono pertanto essere soggetti a contratti di servizio diversi.

Questi concetti di alto livello verranno illustrati in modo più dettagliato in ognuna delle sezioni in cui vengono descritti i servizi di base di Azure, insieme agli obiettivi di disponibilità di ogni servizio o componente e alle indicazioni sulla progettazione della disponibilità. Tenere presente che il data center è ancora un singolo punto di errore per applicazioni di grandi dimensioni; dall'alimentazione elettrica (per un esempio fare clic qui) all'errore di sistema (per un esempio fare clic qui), i problemi dell'infrastruttura e dell'applicazione hanno comportato la riduzione dei data center. Anche se in casi relativamente rari, le applicazioni per le quali sono richiesti livelli massimi di tempo di attività devono essere distribuite in più data center ridondanti.

Per distribuire le applicazioni in più data center, sono necessarie numerose infrastrutture e funzionalità dell'applicazione:

  • Logica dell'applicazione per instradare gli utenti dei servizi al data center appropriato, in base alla geografia, al partizionamento utente o ad altra affinità logica.

  • Sincronizzazione e replica dello stato dell'applicazione tra i data center, con livelli di coerenza e latenza appropriati.

  • Distribuzione autonoma delle applicazioni, in modo da ridurre le dipendenze tra i data center, vale a dire evitare situazioni in cui un errore nel data center A generi un errore nel data center B.

Come per la progettazione di applicazioni caratterizzate dalla disponibilità, anche la compilazione di soluzioni di ripristino di emergenza, in caso di perdita di data center, ha richiesto tempo, energie e capitali ingenti. In questa sezione si esamineranno con attenzione approcci e considerazioni per fornire continuità aziendale in situazioni di errore del sistema o di perdita di dati (generate dal sistema o dall'utente), vale a dire quelle situazioni in cui il termine "ripristino di emergenza" ha assunto una connotazione specifica per gli approcci di implementazione nella community del database.

La continuità aziendale viene garantita grazie a:

  • Gestione della disponibilità e dell'accesso a sistemi aziendali critici (applicazioni eseguite nello stato durevole) in caso di errore irreversibile a livello di infrastruttura.

  • Gestione della disponibilità e dell'accesso a dati aziendali critici (stato durevole) in caso di errore irreversibile a livello di infrastruttura.

  • Gestione della disponibilità di dati aziendali critici (stato durevole) in caso di errore, eliminazione, modifica o danneggiamento accidentale da parte dell'operatore.

I primi due elementi vengono in genere trattati nel contesto del ripristino di emergenza geografico (geo-DR, Geographic Disaster Recovery), mentre il terzo nel dominio di ripristino dei dati e di backup dei dati.

In Azure viene modificata in modo significativo l'equazione per la disponibilità di sistemi aziendali critici, consentendo una rapida distribuzione, geograficamente dislocata, di applicazioni chiave in data center di tutto il mondo. In effetti, il processo di rollout di un'applicazione geograficamente distribuita è leggermente diverso dal rollout di un singolo servizio cloud.

La sfida principale rimane la gestione dell'accesso allo stato durevole. L'accesso ai servizi con stato durevole (ad esempio il Servizio di archiviazione Azure e il database SQL) nei data center produce in genere risultati non ottimali a causa della latenza elevata e/o variabile e non soddisfa i requisiti di continuità aziendale in caso di errore di data center.

Come per la resilienza, molti servizi di Azure forniscono la replica geografica automatica o dispongono di relative informazioni. Ad esempio, se non diversamente configurato in modo specifico, tutte le operazioni di scrittura nella risorsa di archiviazione di Azure (BLOB, coda o tabella) vengono replicate automaticamente in un altro data center. Ogni data center è dotato di una destinazione "mirror" specifica all'interno della stessa area geografica. In questo modo si riducono notevolmente operazioni e tempi necessari per fornire soluzioni di ripristino di emergenza tradizionali in Azure. Nelle sezioni successive verrà fornita una panoramica delle funzionalità di replica geografica dei servizi di base di Azure tramite cui viene gestito lo stato durevole.

Per mantenere la continuità aziendale in caso di errore da parte dell'utente o dell'operatore, vi sono ulteriori considerazioni di cui tener conto nella progettazione delle applicazioni. Sebbene il Servizio di archiviazione Azure offra funzionalità di controllo limitate tramite l'analisi dell'archiviazione, descritta in una sezione successiva, non vengono fornite ulteriori funzionalità di ripristino temporizzato. Per i servizi che richiedono resilienza, in caso di eliminazione o modifica accidentale, sarà necessario esaminare approcci incentrati sull'applicazione, ad esempio la copia periodica di BLOB in un account di archiviazione diverso.

Il database SQL offre funzionalità di base per la gestione di snapshot cronologici dei dati, tra cui la copia e l'importazione e/o esportazione del database tramite file bacpac. Queste opzioni verranno illustrate in dettaglio più avanti in questo documento.

Con la scala elastica fornita dalla piattaforma Azure, la curva dell'offerta si avvicina di molto a quella della domanda, invece di presentare una grande quantità di capacità aggiuntiva per soddisfare eventuali carichi massimi.

Utilizzando la scala elastica, il costo dei prodotti viene basato sugli elementi seguenti:

  • Numero di unità di scala impiegate in una soluzione: macchine virtuali, account di archiviazione e così via, che costituiscono la scala

  • Grado di efficienza del lavoro effettuato tramite le unità di scala in questione.

Il termine densità dell'applicazione utilizzato in questo documento indica la quantità di lavoro eseguibile per una capacità specificata. Grazie a servizi e framework caratterizzati da una densità maggiore è possibile eseguire una quantità di lavoro superiore per una specificata distribuzione di risorse; pertanto, migliorando la densità è possibile ridurre la capacità distribuita, e quindi il costo, oppure è possibile assorbire carico aggiuntivo con la stessa capacità distribuita. La densità si basa su due fattori chiave:

  • Grado di efficienza del lavoro effettuato all'interno di un'unità di scala. Si tratta del modulo tradizionale di ottimizzazione delle prestazioni, cioè la gestione di blocchi e di conflitti di thread e l'ottimizzazione di algoritmi e di query SQL.

  • Grado di efficienza del lavoro coordinato attraverso le unità di scala. In una realtà in cui i sistemi sono costituiti da numerose unità più piccole, la possibilità di mettere insieme queste ultime in modo efficiente è essenziale per poter ottenere un risultato ottimale. Per questa operazione è richiesta la comunicazione tra i componenti di framework e di strumenti, ad esempio stack per messaggi SOAP, quali chiamate WCF, ORM (ad esempio Entity Framework) e TDS (codice client SQL), e serializzazione dell'oggetto, ad esempio contratti dati o JSON.

Oltre alle tecniche di ottimizzazione tradizionali utilizzate in un singolo computer o database, l'ottimizzazione della comunicazione e delle operazioni distribuite è un aspetto fondamentale per garantire un servizio di Azure scalabile ed efficiente. Queste ottimizzazioni chiave vengono illustrate in dettagliato nelle sezioni successive:

  • Soluzioni "voluminose", non "frammentate". Per ogni operazione distribuita, vale a dire una che si verifica in una chiamata di rete, esiste una determinata quantità di overhead per il frame, la serializzazione, l'elaborazione e così via del pacchetto. Per ridurre l'overhead, provare a inviare in batch meno operazioni "voluminose", anziché più operazioni "frammentate". Si tenga presente che l'invio in batch di operazioni granulari comporta un aumento della latenza, nonché il rischio di perdita di dati. Di seguito sono riportati esempi di comportamento di invio in batch appropriato:

    • SQL. Esecuzione di più operazioni in un singolo batch.

    • Servizi REST e SOAP (ad esempio WCF). Utilizzo di interfacce operazioni incentrate sui messaggi, anziché uno stile RPC "frammentate", ed eventuale applicazione di un approccio basato su REST, se possibile.

    • Risorsa di archiviazione di Azure (BLOB, tabelle e code). Pubblicazione di più aggiornamenti in un batch, anziché singolarmente.

  • Impatto della serializzazione. Per lo spostamento di dati tra computer, nonché all'interno e all'esterno di una risorsa di archiviazione durevole, è in genere necessaria la serializzazione dei dati in un formato di trasmissione. L'efficienza (tempo impiegato e spazio utilizzato) di questa operazione influenza rapidamente le prestazioni complessive dell'applicazione di sistemi più ampi.

    • Utilizzare framework di serializzazione altamente efficienti.

    • Utilizzare JSON per le comunicazioni con dispositivi o per applicazioni interoperabili (leggibili).

    • Utilizzare una serializzazione binaria molto efficiente (ad esempio protobuf o Avro) per comunicazioni da servizio a servizio in caso di controllo di entrambi gli endpoint.

  • Utilizzare framework efficienti. Sono disponibili numerosi framework avanzati per lo sviluppo, con ampi set di funzionalità complesse. L'aspetto negativo di molti di questi framework è che spesso si paga il costo di prestazioni per funzionalità che non verranno mai utilizzate.

    • Isolare i servizi e le API client di interfacce generiche per consentire la sostituzione o la valutazione affiancata (tramite le factory statiche o un'inversione del contenitore controlli). Specificare, ad esempio, un livello di connessione di memorizzazione nella cache utilizzando un'interfaccia generica, anziché un'implementazione specifica, ad esempio Azure Caching.

Nella sezione precedente sono stati illustrati concetti e prospettive di progettazione chiave per compilare applicazioni in cui si utilizza l'infrastruttura cloud fornita da Azure. In questa sezione si esamineranno le funzionalità e i servizi di base della piattaforma, illustrandone funzionalità, limiti della scala e modelli di disponibilità.

Dal momento che tutti i servizi o componenti dell'infrastruttura di Azure forniscono una capacità limitata con un contratto di servizio sulla disponibilità, comprendere questi limiti e comportamenti è fondamentale per scegliere la progettazione appropriata per obiettivi di scalabilità personalizzati e contratto di servizio dell'utente finale. Ognuno dei servizi di base di Azure viene presentato nel contesto di quattro punti principali: funzionalità e relative finalità, densità, scalabilità e disponibilità.

Una sottoscrizione di Azure è l'unità di base per amministrazione, fatturazione e quote di servizio. Ogni sottoscrizione di Azure è caratterizzata da un set di quote predefinito che può essere aumentato contattando il supporto tecnico. Inoltre, la relativa finalità è impedire la presenza di eccedenze e l'utilizzo di risorse indesiderati.

A ogni sottoscrizione sono assegnati un proprietario dell'account e un gruppo di coamministratori, autorizzati tramite account Microsoft (precedentemente Live ID), che dispongono del controllo assoluto sulle risorse della sottoscrizione tramite il portale di gestione. Essi possono creare gli account di archiviazione, distribuire i servizi cloud, modificare le configurazioni, nonché aggiungere o rimuovere coamministratori.

Le API di gestione (servizi Web basati su REST) di Azure dispongono di un'interfaccia di automazione per la creazione, configurazione e distribuzione di servizi di Azure, utilizzati dal portale di gestione sottostante. L'accesso a queste API viene limitato tramite certificati di gestione.

 

Servizio Limite predefinito

Servizi cloud

20

Account di archiviazione

20

Core

20

Server logici del database SQL

5

TipSuggerimento
Per informazioni aggiornate sui limiti del servizio e sulla sottoscrizione Azure, vedere la pagina relativa a limiti, quote e vincoli del servizio e alla sottoscrizione Azure

Un servizio cloud Azure, precedentemente denominato servizio ospitato, è l'unità di base per la distribuzione e la scala. Ogni servizio cloud è costituito da due distribuzioni, di produzione e di gestione temporanea, ognuna con un set di ruoli. Nel servizio cloud sono disponibili una voce DNS pubblica nel formato servicename.cloudapp.net per la distribuzione di produzione e una voce DNS di distribuzione di gestione temporanea nel formato someguid.cloudapp.net.

In ogni distribuzione sono inclusi uno o più ruoli, un ruolo Web o un ruolo di lavoro, in cui, a loro volta, sono incluse una o più istanze (macchine virtuali non durevoli). In ogni istanza è contenuto uno snapshot identico, non modificabile e non durevole di un pacchetto software per il ruolo in questione, vale a dire che in tutte le istanze in un determinato ruolo è stata distribuita la stessa build. In queste istanze viene eseguita una versione specializzata per Azure di Windows Server, con molti servizi disabilitati per impostazione predefinita per una sicurezza aggiuntiva, configurati per un utilizzo ottimale dell'infrastruttura dei servizi e delle funzionalità di rete e così via di Azure. Inoltre, in queste istanze, per impostazione predefinita, vengono applicate automaticamente patch dall'infrastruttura di Azure. L'applicazione di patch attiva viene gestita tramite uno schema di aggiornamenti in sequenza, descritto di seguito.

I servizi cloud possono essere distribuiti in qualsiasi data center di Azure, direttamente, scegliendo l'area di destinazione durante la creazione del servizio, o tramite un gruppo di affinità. Un gruppo di affinità è un riferimento indiretto a una destinazione di distribuzione utilizzabile nella distribuzione efficiente di tutti i componenti di un'applicazione nello stesso data center.

I ruoli Web sono preconfigurati con un'istanza di IIS, tramite cui viene ospitato il codice dell'applicazione. Il codice dell'applicazione ospitato nei ruoli di lavoro viene eseguito nell'host applicazioni preconfigurato con esecuzione prolungata. Ogni servizio cloud può disporre di un massimo di 25 ruoli. La configurazione predefinita dei ruoli prevede l'esecuzione del codice .NET, ma un ruolo può essere configurato per eseguire qualsiasi codice compatibile con Windows Server, ad esempio Java, Python, Ruby, node.js e così via. Tutte le funzionalità della piattaforma riportate in questo documento sono disponibili da qualsiasi piattaforma, ma è possibile che venga richiesto uno sviluppo aggiuntivo proxy client la cui destinazione sono le API basate su REST.

A tutte le istanze, all'interno di un servizio cloud, vengono assegnati indirizzi IP privati (nel blocco 10.x). Tutte le connessioni in uscita risultano provenire da un singolo indirizzo IP virtuale, o VIP, vale a dire l'indirizzo IP virtuale della distribuzione del servizio cloud. Tutte le connessioni in ingresso devono passare tramite endpoint configurati. Tramite questi endpoint viene fornito l'accesso con bilanciamento del carico a porte e ruoli interni. Ad esempio, per impostazione predefinita le connessioni HTTP/HTTPS in ingresso (porte 80 e 443) alla distribuzione del servizio cloud sono con bilanciamento del carico in tutte le istanze disponibili del ruolo Web primario.

Si noti che la latenza tra i servizi, cioè l'attraversamento di NAT esternamente a un servizio cloud e tramite il bilanciamento del carico in un altro, è molto più variabile rispetto all'equivalente locale ed è uno dei motivi per cui, per la scalabilità, si preferiscono connessioni tra servizi in batch o "voluminosi".

L'infrastruttura di Azure fornisce inoltre un servizio di configurazione disponibile per tutte le istanze nella distribuzione del servizio cloud. Un set statico di chiavi di configurazione previste è disponibile nella definizione del servizio, come parte del ciclo di sviluppo, con il set iniziale di valori di configurazione distribuiti insieme al servizio quando pubblicato in Azure. Questo set di valori di configurazione è disponibile come ricerca runtime per tutte le istanze presenti nella distribuzione del servizio e può essere modificato in fase di esecuzione tramite un'interfaccia REST, il portale di Azure o uno script di PowerShell.

Quando la configurazione di runtime viene modificata, è possibile che a tutte le istanze vengano associate (nel codice dell'applicazione) la notifica della modifica della configurazione e, di conseguenza, la gestione interna dei relativi aggiornamenti. Se il codice dell'applicazione non viene scritto per acquisire l'evento di modifica della configurazione, nel ruolo di tutte le istanze si verificherà un riavvio in sequenza per aggiornare la relativa configurazione.

Lo stato di ogni istanza non è durevole. Qualsiasi configurazione al di sopra dell'immagine di Azure di base (una macchina virtuale di Windows Server specializzata) deve essere eseguita all'avvio per creare contatori delle prestazioni, ottimizzare le impostazioni IIS, installare il software dipendente e così via. Questi script di configurazione vengono in genere eseguiti come attività di avvio definita dalla configurazione del servizio cloud.

All'interno di un servizio cloud, le informazioni fornite dall'infrastruttura di Azure sulla configurazione, sugli indirizzi IP interni, sulla configurazione del servizio e così via, sono disponibili tramite l'oggetto RoleEnvironment. È possibile accedere alle informazioni di RoleEnvironment per recuperare la configurazione, individuare la topologia di rete e così via, tramite tutti i processi in esecuzione in un'istanza di Azure. È inoltre possibile utilizzare le API di gestione di Azure per accedere a queste informazioni dall'esterno.

Nell'infrastruttura di Azure vengono esposti due concetti di base per gestire errori, riconfigurazione, aggiornamento e applicazione di patch dei componenti, vale a dire i domini di aggiornamento e di errore.

I domini di aggiornamento sono raggruppamenti logici all'interno di un servizio di Azure. Per impostazione predefinita, a ogni servizio sono associati cinque (5) domini di aggiornamento. Questo valore può essere modificato nella definizione del servizio cloud. Qualsiasi modifica o aggiornamento del servizio interessa solo un singolo dominio di aggiornamento per volta. L'applicazione di patch al sistema operativo, la modifica delle dimensioni delle macchine virtuali, l'aggiunta di ruoli o di istanze del ruolo a un servizio in esecuzione o la modifica della configurazione dell'endpoint sono tutti esempi di queste modifiche.

In questo modo è possibile la riconfigurazione attiva di un servizio cloud in esecuzione gestendo, nel contempo, la disponibilità. Per i ruoli contenenti una singola istanza, tramite l'infrastruttura di Azure non è possibile garantire la disponibilità durante le operazioni di aggiornamento; per questo motivo l'esecuzione di ruoli a istanza singola non rispetta il contratto di servizio di Azure.

I domini di errore sono raggruppamenti logici basati sull'hardware sottostante. Sebbene non venga garantito il mapping diretto a una configurazione hardware specifica, il raggruppamento logico può essere considerato come il modo in cui, tramite l'infrastruttura di Azure, le istanze vengono separate automaticamente dalle risorse sottostanti che rappresentano un singolo punto di errore, ad esempio un singolo server fisico sottostante, un rack e così via. Per soddisfare il contratto di servizio, nelle istanze di Azure devono essere distribuiti almeno due domini di errore. Si tratta dell'altra motivo per cui le distribuzioni di ruoli a istanza singola non soddisfano il contratto di servizio di Azure.

Di seguito è riportato un riepilogo degli elementi illustrati in precedenza:

  • L'unità di base di distribuzione e scala in Azure è il servizio cloud che è costituito da un set di ruoli. In ogni ruolo è contenuto un set di istanze del ruolo identiche, in ognuna delle quali viene eseguita una versione configurata del cloud specializzata di Windows Server.

  • Oltre alla topologia fisica (ruoli e istanze) e al codice dell'applicazione, tramite i servizi cloud viene definita una configurazione a livello di servizio. Questa configurazione può essere aggiornata in fase di esecuzione.

  • Ogni ruolo dell'istanza è non durevole (non viene garantito che le modifiche, i file e così via siano persistenti in caso di riavvio, applicazione di patch, errori).

  • In ogni servizio cloud è esposto un singolo IP virtuale per il traffico in ingresso e in uscita. Nel servizio cloud sono esposti endpoint tramite cui viene fornito un mapping con carico bilanciato (round robin) a un ruolo e una porta interni.

  • In Azure vengono utilizzati i domini di aggiornamento per separare logicamente i gruppi di istanze e fornire modifiche o aggiornamenti in sequenza, mantenendo la disponibilità.

  • In Azure vengono utilizzati i domini di errore per raggruppare fisicamente le istanze lontane dai singoli punti di errore, ad esempio l'esecuzione di tutte le istanze nello stesso computer fisico sottostante.

  • Utilizzare più sottoscrizioni per isolare gli ambienti di sviluppo, test, gestione temporanea e produzione.

In ogni ruolo è contenuto un set di una o più istanze. Ognuna di queste istanze è una macchina virtuale in cui viene eseguita una versione specializzata di Windows Server. Le dimensioni delle istanze (macchine virtuali) attualmente disponibili sono cinque: da molte piccole a molto grandi. A ognuna di queste dimensioni viene allocata una certa quantità di CPU, memoria, archiviazione e larghezza di banda.

 

Dimensioni della macchina virtuale Core CPU Memoria Spazio su disco per le risorse di archiviazione locale nei ruoli Web e di lavoro Spazio su disco per le risorse di archiviazione locale in un ruolo di macchina virtuale Larghezza di banda allocata (Mbps)

Molto piccola

Condivisi

768 MB

19.480 MB

(6.144 MB sono riservati per i file di sistema)

20 GB

5

Piccola

1

1,75 GB

229,400 MB

(6.144 MB sono riservati per i file di sistema)

165 GB

100

Media

2

3,5 GB

500,760 MB

(6.144 MB sono riservati per i file di sistema)

340 GB

200

Grande

4

7 GB

1.023.000 MB

(6.144 MB sono riservati per i file di sistema)

850 GB

400

Molto grande

8

14 GB

2.087.960 MB

(6.144 MB sono riservati per i file di sistema)

1.890 GB

800

TipSuggerimento
Per informazioni aggiornate sui limiti del servizio e sulla sottoscrizione Azure, vedere la pagina relativa a limiti, quote e vincoli del servizio e alla sottoscrizione Azure

Se due o più istanze vengono distribuite in diversi domini di errore e di aggiornamento, tramite Azure vengono forniti i seguenti contratti di servizio per i servizi cloud:

  • 99,95% di connettività esterna per ruoli con connessione Internet (quelli con endpoint esterni)

  • 99,9% di problemi dell'istanza del ruolo rilevati entro due minuti e avvio di azioni correttive

Sia le dimensioni sia i conteggi delle istanze del ruolo possono essere modificati dinamicamente in un'applicazione in esecuzione. Nota: la modifica delle dimensioni del ruolo comporta una ridistribuzione in sequenza. Dato l'approccio con scalabilità orizzontale per la compilazione di applicazioni di Azure, la selezione di grandi dimensioni per le istanze non rappresenta necessariamente la scelta ottimale. Questa condizione si applica sia ai costi (perché pagare ciò che non si utilizza) sia alle prestazioni (a seconda che il carico di lavoro sia basato sulla CPU, su operazioni di I/O e così via). Gli approcci per selezionare il numero di istanze e le relative dimensioni sono illustrati dettagliatamente nella sezione "Procedure consigliate" di questo documento.

Tramite il Servizio di archiviazione Azure vengono garantiti dati durevoli di base per Azure e viene fornita l'archiviazione di BLOB (file), code e tabelle (da chiavi a valori). L'account di archiviazione è l'unità di base della scala e della disponibilità tramite cui vengono fornite le seguenti funzionalità. Tutte le comunicazioni con il servizio di archiviazione sono basate su un'interfaccia REST tramite HTTP.

TipSuggerimento
Per informazioni aggiornate sui limiti del servizio e sulla sottoscrizione Azure, vedere la pagina relativa a limiti, quote e vincoli del servizio e alla sottoscrizione Azure

Tramite il contratto di servizio sulla disponibilità del Servizio di archiviazione Azure viene garantito che, per almeno il 99,9% del tempo, le richieste formattate correttamente per aggiungere, aggiornare, leggere ed eliminare dati verranno elaborate in modo appropriato e che, inoltre, per gli account di archiviazione sarà disponibile la connettività al gateway Internet.

Questi limiti vengono condivisi tra tutti gli utilizzi del singolo account di archiviazione, cioè il numero di operazioni eseguite al secondo e la larghezza di banda complessiva sono condivisi tra tabelle, BLOB e code. Se un'applicazione supera il numero totale di operazioni eseguite al secondo, tramite il servizio può essere restituito un codice HTTP 503 in cui viene indicato che il server è occupato. Le operazioni sono specifiche per ogni aspetto di archiviazione (tabelle, code o BLOB) e vengono descritte nelle sottosezioni seguenti.

Secondo la metafora dei container per le spedizioni utilizzata in precedenza, ogni account di archiviazione è un container caratterizzato da una capacità specifica. Per poter superare il limite di un singolo account (container per le spedizioni) è richiesto l'utilizzo di più account nella stessa applicazione.

Tramite il Servizio di archiviazione Azure vengono garantite, per impostazione predefinita, disponibilità e resilienza; tutte le operazioni di scrittura o gli aggiornamenti in questo servizio vengono replicati in modo trasparente e coerente nei tre nodi di archiviazione, che si trovano in diversi domini di aggiornamento e di errore. L'accesso al Servizio di archiviazione Azure viene controllato tramite l'autenticazione a fattore singolo sotto forma di chiavi di accesso. A ogni account di archiviazione sono associate due chiavi, una primaria e una secondaria, tramite cui viene consentita una disponibilità continua in caso di rotazione della chiave primaria. I dati nel Servizio di archiviazione Azure vengono automaticamente replicati a livello geografico in un data center "mirror" (a meno che questa funzionalità non venga disabilitata tramite il portale). La replica geografica è opaca e viene utilizzato il reindirizzamento DNS per eseguire il failover dei client nella posizione secondaria in caso di errore nel data center principale.

Si noti che anche se tramite il Servizio di archiviazione Azure viene fornita la resilienza dei dati attraverso repliche automatizzate, non è possibile evitare il danneggiamento dei dati da parte del codice dell'applicazione (o di sviluppatori/utenti) a causa di eliminazioni e aggiornamenti accidentali o indesiderati e così via. Per mantenere la conformità dei dati in caso di errore dell'applicazione o da parte dell'utente sono richieste tecniche più avanzate, ad esempio la copia dei dati in un percorso di archiviazione secondario con un log di controllo. Tramite l'archiviazione BLOB viene fornita una funzionalità snapshot tramite cui è possibile creare snapshot temporizzati di sola lettura di contenuti BLOB che possono essere utilizzati come base per una soluzione di conformità dei dati per i BLOB.

Tramite il Servizio di archiviazione Azure viene fornita la telemetria attraverso la relativa funzionalità di analisi dell'archiviazione mediante cui vengono raccolti ed esposti i dati di utilizzo relativi alle singole chiamate di archiviazione a tabelle, code e BLOB. L'analisi dell'archiviazione deve essere abilitata per ogni account di archiviazione con criteri di raccolta (raccolta per tutti, solo per le tabelle e così via) e di conservazione (durata di mantenimento dei dati).

Tramite l'archiviazione BLOB viene fornito il servizio di gestione dei file in Azure che offre un metodo economico e a disponibilità elevata per archiviare i dati bulk non strutturati. Tramite il servizio vengono forniti due tipi di BLOB:

  • BLOB in blocchi. I BLOB in blocchi sono progettati per gestire in modo efficiente BLOB di dati di grandi dimensioni. Ogni BLOB in blocchi è costituito da un massimo di 50.000 blocchi e le dimensioni massime di ognuno sono pari a 4 MB (con una dimensione complessiva massima di 200 GB). I BLOB in blocchi supportano il caricamento parallelo per spostare contemporaneamente e in modo efficiente file di grandi dimensioni nelle reti. È possibile inserire, sostituire o eliminare singoli blocchi, ma non modificarli sul posto.

  • BLOB di pagine. I BLOB di pagine sono progettati per offrire in modo efficiente operazioni casuali di lettura/scrittura, ad esempio l'accesso a un file VHD. Le dimensioni massime di ogni BLOB di pagine sono pari a 1 TB, costituito da pagine da 512 byte. È possibile aggiungere o aggiornare pagine singole o gruppi di pagine tramite una sovrascrittura sul posto.

I limiti di progettazione per l'archiviazione BLOB sono elencati nella tabella seguente. Si tenga presente che tutte queste operazioni influiscono sui limiti complessivi dell'account di archiviazione.

 

Categoria di BLOB Limite

Dimensioni massime BLOB (in blocchi)

200 GB (blocchi da 50 k)

Dimensioni massime BLOB

4 MB

Dimensioni massime BLOB (di pagine)

1 TB

Dimensioni della pagina

512 byte

Larghezza di banda massima/BLOB

480 Mbps

In caso di superamento dei limiti di dimensioni o della larghezza di banda di un singolo BLOB, tramite le applicazioni è possibile scrivere in più file BLOB simultanei (o sequenziali). Se tramite l'applicazione si superano i limiti di un singolo account di archiviazione, utilizzare più account di archiviazione per ottenere una capacità maggiore.

Tramite le code di Azure viene fornito un servizio di messaggistica (negoziata) intermedio tra i server di pubblicazione e i sottoscrittori. Le code supportano più server di pubblicazione e sottoscrittori simultanei, ma tramite esse non vengono esposte in modo nativo primitive di messaggistica di ordine superiore, ad esempio il routing di pubblicazione/sottoscrizione o basato su argomenti. In genere vengono utilizzate per distribuire gli elementi di lavoro (ad esempio messaggi, documenti, attività e così via) in un set di istanze del ruolo di lavoro o tra più servizi ospitati e così via.

I messaggi delle code vengono eliminati automaticamente dopo 7 giorni se non vengono recuperati ed eliminati da un'applicazione. Tramite le code viene fornito il disaccoppiamento tra i server di pubblicazione e i consumer di informazioni; pertanto finché entrambi i lati dispongono della chiave dell'account di archiviazione e del nome della coda, la comunicazione è assicurata.

 

Categoria di coda Limite

Numero massimo di messaggi in coda

N/D (fino al limite dell'account di archiviazione)

Durata massima di un messaggio

1 settimana (eliminato automaticamente)

Dimensioni massime del messaggio

64 KB

Velocità effettiva massima

~ 500 messaggi/secondo

Le code vengono utilizzate per passare i messaggi di controllo, non i dati non elaborati. Se i messaggi sono troppo grandi per una coda, eseguire il refactoring dei messaggi per separare i dati e il comando. Archiviare i dati nell'archivio BLOB con un riferimento (URI) ai dati e la finalità (cioè l'utilizzo dei dati in un archivio BLOB) archiviata in un messaggio di coda.

Per aumentare la velocità effettiva in un'unica coda, inviare in batch più messaggi in un singolo messaggio, quindi utilizzare il comando di aggiornamento del messaggio per tenere traccia dello stato delle attività del messaggio di incapsulamento. Un'altra tecnica consiste nell'inserire più messaggi in un BLOB con un puntatore al BLOB nel messaggio della coda.

Se per l'applicazione è richiesta una velocità effettiva maggiore rispetto a quella offerta da una singola coda, utilizzare più code simultanee. In questo contesto, tramite l'applicazione devono essere implementati un partizionamento e una logica di routing appropriati.

Tramite l'archiviazione tabelle di Azure viene fornito un archivio caratterizzato da coerenza, scalabilità e durata elevate per i dati a colonne (bidimensionali). Viene fornita una semantica { chiave di partizione, chiave di riga } -> { dati[] } per l'archiviazione e l'accesso ai dati, come mostrato nel diagramma riportato di seguito. Ogni tabella viene suddivisa in base a partizioni in cui, a loro volta, sono contenute entità. A ogni entità può essere associato il proprio schema (flat) o elenco di proprietà (colonne).

Ogni partizione supporta fino a 500 operazioni al secondo; a sua volta, ogni tabella supporta il numero massimo di operazioni disponibili nell'account di archiviazione. Dal momento che in ogni entità non sono contenuti solo i dati effettivi, ma anche i metadati a colonne (poiché a ogni entità può essere associato uno schema diverso), è consigliabile non utilizzare nomi di colonne lunghi, in particolare in caso di approccio di grandi dimensioni.

 

Categoria di tabella Limite

Numero massimo di operazioni al secondo per partizione

500

Dimensioni massime dell'entità (nomi di colonna + dati)

1 MB

Dimensioni massime della colonna (byte[] o string)

64 KB

Numero massimo di righe

N/D (fino al limite dell'account di archiviazione)

Tipi di dati supportati

byte[], Boolean, datetime, double, Guid, int32, int64, string

Le dimensioni massime delle singole entità (che possono essere considerate come righe) sono pari a 1 MB e le singole colonne sono limitate a un massimo di 64 KB. I tipi di dati supportati sono elencati nella tabella precedente; per i tipi non supportati (ad esempio DateTimeOffset) è richiesto un proxy di serializzazione nel codice dell'applicazione (ad esempio l'archiviazione di DateTimeOffset in un formato di stringa standard).

L'archiviazione tabelle fornisce l'accesso ai dati archiviati tramite le chiavi associate a partizioni ed entità, nonché alla relativa analisi. Supporta la proiezione di filtri, infatti un'espressione di filtro può essere sottoposta a push nell'archiviazione tabelle come parte della query ed eseguita nell'archiviazione tabelle. Tramite l'archiviazione tabelle non vengono forniti indici secondari, pertanto per qualsiasi ricerca non basata sulla chiave di partizione o di entità è richiesta l'analisi di una tabella e/o partizione. Se nelle partizioni è contenuto un numero non semplice di entità, l'impatto sulle prestazioni è in genere significativo.

Tramite ogni elaborazione di query per cui sono richiesti più di 5 secondi viene restituito un token di continuazione che può essere utilizzato dall'applicazione per continuare a ricevere i risultati della query. Nelle query tramite cui vengono recuperate più di 1.000 entità deve essere utilizzato un modello di paging per riportare i dati in blocchi da 1.000 che sono supportati in modo nativo dall'API dell'archiviazione tabelle.

Le uniche espressioni di query attualmente supportate nell'archiviazione tabelle sono l'applicazione di filtri e la selezione di proprietà specifiche; tramite l'archiviazione tabelle non viene fornita un'aggregazione lato server o una semantica di raggruppamento. Per compilare applicazioni per cui sono richieste funzionalità di analisi o aggregazione avanzate, spesso la scelta migliore consiste nell'archiviare i dati sotto forma di aggregazione o utilizzare un motore relazionale, ad esempio il database SQL di Azure. In alcune applicazioni viene utilizzato un approccio ibrido, vale a dire si esegue l'aggregazione dei dati dall'archiviazione tabella in un database SQL ausiliario, utilizzato successivamente per scopi di report e di query.

La scelta di una funzione di partizionamento appropriata è molto importante in termini di utilizzo efficiente dell'archiviazione tabella. Sono disponibili due opzioni principali per il tipo di funzione di partizionamento:

  • Ora. Utilizzate in genere per archiviare i dati della serie temporale, ad esempio i contatori delle prestazioni di Diagnostica Azure (utilizzo illustrato nella sezione sulla telemetria in questo documento), le funzioni di partizionamento basate sul tempo consentono di convertire l'ora corrente in un valore che rappresenta una finestra temporale (minuti, ora correnti e così via).

    Tramite funzioni di questo tipo è possibile eseguire una ricerca e utilizzare il percorso di una partizione specifica in modo efficiente, dal momento che la clausola di filtro per l'archiviazione tabella supporta >=, <= e così via. Tuttavia, le funzioni in questione possono essere soggette a limitazione se la finestra temporale scelta non è sufficientemente ampia e si verifica un evento di picco. Ad esempio, se la funzione di partizione scelta è il minuto corrente e si verifica un evento di picco, è possibile che molti clienti stiano tentando di scrivere simultaneamente nella stessa partizione. Questa situazione non interessa solo la velocità effettiva per l'operazione di inserimento, ma anche quella per l'esecuzione di una query.

  • Dati. Tramite le funzioni di partizionamento incentrate sui dati il valore di partizione viene calcolato in base a una o più proprietà dei dati da archiviare (o recuperare). La scelta di una funzione di partizionamento basata sui dati appropriata dipende da diversi fattori: modelli di query, densità delle chiavi di partizione (numero di entità che verranno inserite in una partizione) e aumento imprevisto (condizione che può riverlarsi complessa per il ribilanciamento di tabelle di grandi dimensioni). Tra i modelli comuni sono inclusi:

    • Singolo campo. La chiave di partizione è un singolo campo nei dati di origine, ad esempio un ID cliente per informazioni sugli ordini.

    • A più campi. La chiave di partizione o di riga è un raggruppamento, in genere una concatenazione, di più campi nei dati di origine. Quando si selezionano le chiavi di partizione, si noti che per le operazioni batch è necessario che tutte le entità si trovino nella stessa partizione, cioè dispongano della stessa chiave di partizione.

    • Campo calcolato. La chiave di partizione viene calcolata da uno o più campi, in base a una funzione deterministica. Un relativo esempio comune è la distribuzione dei profili utente in più partizioni. L'ID utente viene sottoposto ad hashing utilizzando una funzione corrispondente progettata per una distribuzione relativamente uniforme, successivamente il modulo viene eseguito in base al numero di partizioni desiderate.

Per qualsiasi applicazione non semplice è necessario l'utilizzo di più partizioni. Anche in caso di tabelle con un numero limitato di entità totali, ad esempio duecento, se tramite l'applicazione verranno eseguite diverse migliaia di richieste al secondo, saranno necessarie più partizioni per la velocità effettiva:

  • Singola tabella/singola partizione. Opzione semplicissima (valore costante della chiave di partizione), idonea per carichi di lavoro in scala ridotta con numero limitato di dati e requisiti di velocità effettiva per le richieste (< 500 entità/sec).

  • Tabella singola/più partizioni. Opzione tipica per la maggior parte delle distribuzioni. Scegliere con attenzione le chiavi di partizione per l'allineamento ai modelli di query di destinazione.

  • Più account di archiviazione/più partizioni. Se si prevede un carico superiore a 5.000 operazioni al secondo, è necessario l'utilizzo di tabelle distribuite tra più account di archiviazione.

La scelta di un ribilanciamento (ripartizionamento) dei dati può essere un'operazione costosa, che comporta la lettura e la copia di tutte le entità con nuove chiavi di partizione e successiva eliminazione dei dati non aggiornati. Si noti che non esiste alcuna limitazione di dimensioni minime per una partizione. Le partizioni possono essere costituite anche da una singola entità, vale a dire una riga.

Se per l'applicazione è necessaria una velocità effettiva maggiore rispetto a quella fornita da una singola tabella (dopo un'attenta selezione della partizione), utilizzare più tabelle simultanee in account di archiviazione diversi. In questo contesto, tramite l'applicazione sarà necessario implementare la logica di routing appropriata per selezionare l'account di archiviazione più idoneo.

La rete CDN di Azure fornisce una modalità efficiente per memorizzare nella cache il contenuto statico (proveniente da BLOB o dall'output dell'applicazione) in una rete per la memorizzazione nella cache distribuita a livello globale. In questo modo viene diminuito il carico di lavoro nell'applicazione per recapitare il contenuto statico. Inoltre, viene migliorata l'esperienza complessiva dell'utente finale.

Tramite il contratto di servizio sulla disponibilità della rete CDN viene garantito il recapito degli oggetti memorizzati nella cache con una disponibilità del 99,9% su base mensile.

Per utilizzare la rete CDN è necessaria l'attivazione della funzionalità per la sottoscrizione. È possibile memorizzare nella cache dal contenuto di BLOB (proveniente da contenitori di accesso anonimo/disponibili pubblicamente) al contenuto anonimo dell'output dell'applicazione, ad esempio http://www.myapp.com/cdn/somepage.aspx.

In generale, nel caso di applicazioni su larga scala, tutto il contenuto statico a cui si accede normalmente (immagini, CSS e così via) dovrebbe essere recapitato tramite la rete CDN con criteri di scadenza della cache appropriati.

Si consideri, ad esempio, un archivio ebook online con 1 milione di titoli. L'inserimento del contenuto (immagini e così via) di tutti i titoli nella rete CDN sarà un'operazione molto costosa, dal momento che l'accesso alla maggior parte di esso non sarà frequente e per lo stesso contenuto saranno necessari continui aggiornamenti in termini di scadenza, mentre l'inserimento del solo contenuto principale, ad esempio i primi 50 titoli, garantirebbe il giusto rapporto fra contenuto memorizzato nella cache e prezzo.

Uno degli elementi di base per il corretto recapito di un servizio su larga scala è la telemetria, vale a dire una visione completa del funzionamento, delle prestazioni e dell'esperienza utente dell'applicazione. Per gli approcci di telemetria per applicazioni Azure è necessario considerare sia la scalabilità orizzontale e la natura distribuita della piattaforma, sia i servizi disponibili della piattaforma per la raccolta, l'analisi e l'utilizzo della telemetria.

Il componente di base della tecnologia per la raccolta e la comprensione della telemetria in Azure è Diagnostica Azure (WAD, Azure Diagnostics). Questo componente è costituito da un agente in grado di raccogliere i dati da singole istanze e inoltrarli a un punto di raccolta centrale (account di archiviazione), nonché da un set di strutture e convenzioni standard per l'archiviazione e l'accesso dei dati. L'agente supporta diversi approcci di configurazione, tra cui il codice (.NET), un file di configurazione incorporato nel codice del progetto distribuito o un file di configurazione centralizzato distribuito nell'archiviazione BLOB. La configurazione è parzialmente dinamica nell'ultima istanza, pertanto i file di diagnostica aggiornati possono essere inseriti nell'archiviazione BLOB e successivamente spostati negli agenti di destinazione.

La configurazione di WAD fornisce una serie di origini dati, ognuna delle quali viene raccolta periodicamente, inviata in batch tramite una sessione Event Tracing for Windows (denominata ETW) e pubblicata nell'account di archiviazione di destinazione. Tramite l'agente vengono affrontati eventuali problemi di connessione temporanei, vengono effettuati tentativi e così via. Di seguito sono elencate le origine dati disponibili:

  • Contatori delle prestazioni. Subset di valori dei contatori delle prestazioni (CPU, memoria e così via) acquisiti in una sessione ETW locale e gestiti in modo temporaneo periodicamente nell'archiviazione tabella.

  • Registri eventi di Windows. Subset di valori di record di eventi di Windows (applicazione, sistema e così via) acquisiti in una sessione ETW locale e gestiti in modo temporaneo periodicamente nell'archiviazione tabella.

  • Log di Azure. Log applicazioni (messaggi di traccia) pubblicati dal codice dell'applicazione (tramite System.Diagnostics.Trace) e acquisiti da un listener di traccia DiagnosticMonitorTraceListener. Questi log vengono pubblicati nella tabella dei contatori delle prestazioni di WAD nell'account di archiviazione di destinazione.

  • Registri di IIS 7.0. Informazioni standard dei registri IIS sulle richieste registrate tramite l'applicazione IIS stessa (solo ruoli Web). I registri vengono raccolti in file locali e gestiti in modo temporaneo periodicamente nell'archiviazione BLOB.

  • Registri di richieste non riuscite di IIS. Informazioni provenienti da IIS sulle richieste non riuscite, raccolte in file locali e gestiti in modo temporaneo periodicamente nell'archiviazione BLOB.

  • Dump di arresto anomalo del sistema. In caso di arresto anomalo del sistema, i registri sullo stato del sistema operativo vengono acquisiti e pubblicati nell'archiviazione BLOB.

  • Origine dati. Tramite WAD è possibile monitorare directory locali aggiuntive, ad esempio directory log nell'archiviazione locale, e copiare periodicamente i dati in un contenitore personalizzato nell'archiviazione BLOB.

Ognuna di queste origini dati è configurata con il subset di dati da raccogliere, ad esempio l'elenco dei contatori delle prestazioni, e l'intervallo di raccolta o di pubblicazione. Sono inoltre disponibili una serie di script di PowerShell per modificare la configurazione di runtime o per forzare una pubblicazione immediata di dati dagli agenti nell'account di archiviazione di destinazione.

ImportantImportante
Registrare la telemetria in un altro account di archiviazione. La registrazione della telemetria e dei dati dell'applicazione nello stesso account di archiviazione può comportare gravi problemi di contesa nella scala.

Il database SQL di Azure fornisce un database come servizio, consentendo alle applicazioni di eseguire rapidamente operazioni di provisioning, inserimento dei dati nei database relazionali ed esecuzione di una query sui database in questione. Offre inoltre molte delle funzionalità comuni di SQL Server, eliminando però le attività correlate all'hardware, alla configurazione, all'applicazione di patch e alla resilienza.

noteNota
Il rapporto tra le funzionalità del database SQL e quelle di SQL Server non è equivalente. Il database SQL è progettato per soddisfare una serie di requisiti diversi, esclusivi per le applicazioni cloud (scala elastica, database come servizio per la riduzione dei costi di manutenzione e così via). Per ulteriori informazioni, vedere la pagina http://blogs.msdn.com/b/windowsazure/archive/2012/06/26/data-series-sql-server-in-windows-azure-virtual-machine-vs-sql-database.aspx.

Il servizio viene eseguito in un ambiente condiviso multi-tenant, con database di più utenti e sottoscrizioni in esecuzione nell'infrastruttura compilata nell'hardware apposito (scalabilità verticale, non scalabilità orizzontale).

I database vengono sottoposti a provisioning all'interno di server logici. In ogni server logico sono contenuti, per impostazione predefinita, fino a 150 database, incluso quello master. Per impostazione predefinita, tramite ogni sottoscrizione può essere eseguito il provisioning di cinque (5) server logici, con la possibilità di aumentare questo numero, nonché quello massimo di database per server logico, tramite una chiamata al supporto tecnico.

A ogni server logico viene assegnato un nome DNS generato, pubblico, univoco (nel formato [nomeserver].database.windows.net) e lo stesso indirizzo IP pubblico viene condiviso da tutti i server logici disponibili in una sottoscrizione. L'accesso ai server (e database) logici viene eseguito tramite la porta SQL standard (TCP/1433), con un'API di gestione basata su REST il cui accesso avviene attraverso la porta TCP/833.

Per impostazione predefinita, l'accesso al server logico, e a tutti i relativi database, viene limitato tramite regole firewall basate su IP applicate al portale di gestione di Azure (le regole possono essere impostate nel server logico o nei singoli database). Per poter accedere alle applicazioni Azure e alla connettività diretta dell'applicazione dall'esterno di Azure, ad esempio per la connessione a SQL Server Management Studio, è necessaria la configurazione di regole firewall. Queste regole possono essere configurate tramite il portale di gestione di Azure mediante una chiamata API al servizio di gestione.

Il database SQL fornisce supporto per la maggior parte delle funzionalità chiave disponibili in SQL Server, con diverse importanti eccezioni tra cui:

  • In tutte le tabelle deve essere incluso un INDICE CLUSTER. I dati non possono essere INSERITI in una tabella del database SQL fino a quando non è stato definito un indice di questo tipo.

  • Nessun supporto CLR (Common Language Runtime) incorporato, né mirroring del database, né Service Broker, né compressione dei dati, né partizionamento della tabella.

  • Nessun indice XML; il tipo di dati XML è supportato.

  • Nessun supporto per Transparent Data Encryption, né controllo di dati

  • Nessun supporto per la ricerca full-text

Ogni database, quando creato, è configurato con un limite massimo di dimensioni. I limiti massimi attualmente disponibili sono 1 GB, 5 GB, 10 GB, 20 GB, 30 GB, 40 GB, 50 GB, 100 GB e 150 GB Quando un database raggiunge il limite massimo delle dimensioni, i comandi aggiuntivi INSERT o UPDATE vengono rifiutati. L'esecuzione di query e l'eliminazione dei dati sono però operazioni ancora possibili. Le dimensioni di un database possono inoltre essere create (aumentate o diminuite) eseguendo un comando ALTER DATABASE.

Dal momento che la fatturazione per un database viene effettuata in base alle dimensioni medie utilizzate al giorno, per le applicazioni per le quali si prevede un aumento rapido e imprevisto è possibile scegliere di impostare inizialmente le dimensioni massime del database su 150 GB. Per il ridimensionamento di un database oltre i 150 GB è necessario utilizzare un approccio con scalabilità orizzontale, descritto più dettagliatamente nella sezione di seguito.

Il database SQL dispone di una resilienza predefinita all'errore a livello di nodo. Tutte le operazioni di scrittura in un database vengono replicate automaticamente in due o più nodi in background utilizzando una tecnica di commit basata su quorum. Tramite il nodo primario e almeno uno secondario deve essere verificato che l'attività venga scritta nel log delle transazioni prima che quest'ultima venga ritenuta corretta e che tramite essa venga restituito un valore. In caso di errore del nodo viene eseguito automaticamente il failover del database in una delle repliche secondarie. Questa operazione comporta un'interruzione temporanea della connessione per le applicazioni client, uno dei motivi principali in base al quale in tutti i client del database SQL devono essere implementate alcune forme di gestione temporanea della connessione.

Il contratto di servizio sulla disponibilità mensile è pari al 99,9% del tempo di attività, definito come la possibilità di connettersi al database SQL entro 30 secondi in un intervallo di 5 minuti. Gli eventi di failover descritti nel paragrafo precedente si verificano in genere in meno di 30 secondi, ribadendo la necessità che gli errori temporanei di connessione vengano gestiti dall'applicazione.

Le informazioni sull'integrità e sulle prestazioni del database SQL vengono fornite tramite DMV in cui sono contenuti dati sugli aspetti principali del sistema, ad esempio le prestazioni delle query, le dimensioni del database e delle tabelle e così via. Le operazioni di raccolta e analisi delle informazioni da DMV chiave, nonché di integrazione nel framework di approfondimento e telemetria più ampio devono essere gestite dalle applicazioni su base periodica.

Sono disponibili diverse opzioni di continuità aziendale (backup, ripristino) per il database SQL. I database possono essere copiati tramite la funzionalità di copia del database o il servizio di importazione/esportazione dell'applicazione livello dati. A differenza di un file bacpac generato dal servizio di importazione/esportazione, la funzionalità di copia del database fornisce risultati coerenti dal punto di vista transazionale. Entrambe le opzioni vengono eseguite come servizi basati su coda nel data center e non forniscono attualmente un contratto di servizio sul tempo necessario per il completamento.

Si noti che la copia del database e il servizio di importazione/esportazione comportano un livello di carico significativo nel database di origine e possono attivare eventi di contesa o di limitazione delle risorse, descritti nella sezione "Risorse condivise e limitazione" di seguito. Sebbene nessuno di questi approcci garantisca lo stesso livello di backup incrementale supportato da SQL Server, è attualmente disponibile in anteprima una nuova funzionalità per abilitare il ripristino temporizzato. Grazie a questa funzionalità, gli utenti possono eseguire un ripristino temporizzato arbitrario del database entro le ultime 2 settimane.

L'unica tecnica di autenticazione attualmente supportata è l'autenticazione di SQL, per la quale l'unico fattore richiesto è l'accesso tramite nome utente/password in base agli utenti registrati nel database. Active Directory o funzionalità di autenticazione a due fattori non sono ancora disponibili. Si consiglia l'applicazione della crittografia della connessione al database SQL, mediante il supporto di crittografia predefinito disponibile in ADO.NET, ODBC e così via. Le autorizzazioni a livello di database sono coerenti con SQL Server. Per informazioni dettagliate sulla configurazione della sicurezza del database SQL di Azure, vedere Gestione di database e account di accesso in database SQL di Azure.

Il database SQL dispone di un set completo di DMV per esaminare le prestazioni delle query e l'integrità del database. Tuttavia, non viene fornita alcuna infrastruttura automatica per la raccolta e l'analisi di questi dati, né sono disponibili strumenti comuni, ad esempio contatori delle prestazioni a livello di sistema o un profiler collegato direttamente. Gli approcci per la raccolta e l'analisi sono descritti nella sezione sulla telemetria di questo documento.

Come illustrato in precedenza, il database SQL è un servizio multi-tenant in esecuzione in un'infrastruttura condivisa. I nodi fisici sottostanti, sviluppati e distribuiti nell'hardware apposito, vengono condivisi da database di tenant differenti. Altri utenti del sistema possono utilizzare le risorse principali, cioè thread di lavoro, log delle transazioni, I/O e così via, nella stessa infrastruttura sottostante. L'utilizzo delle risorse viene gestito per mantenere i database nei limiti stabiliti per le risorse. Se questi limiti vengono superati, in un tenant o a livello del nodo fisico, tramite il database SQL viene applicata una limitazione di utilizzo o un'interruzione delle connessioni. Questi limiti sono elencati nella tabella riportata di seguito.

 

Risorsa Valore massimo per transazione/sessione Valore massimo per nodo fisico Limite massimo a livello software Limite massimo a livello hardware

Thread di lavoro

N/D

512

305

410

Dimensioni database

Dimensioni massime configurate fino a 150 GB per database

N/D

nessuna.

100%; una volta raggiunto il limite, non sono consentite operazioni di inserimento o aggiornamento

Aumento delle dimensioni del log delle transazioni

2 GB per transazione

500 GB

N/D

N/D

Lunghezza del log delle transazioni

20% di spazio totale di log (100 GB)

500 GB

N/D

N/D

Conteggio blocchi

1 milione per transazione

N/D

N/D

N/D

Blocco delle attività di sistema

20 secondi

N/D

N/D

N/D

Spazio del database temporaneo

5 GB

N/D

N/D

5 GB

Memoria

N/D

N/D

N/D

16 MB oltre i 20 secondi

Richieste concorrenti massime

400 per database

N/D

N/D

N/D

Se viene raggiunto il limite di una transazione, quest'ultima verrà annullata. Se viene raggiunto un limite a livello software da parte di un database, le transazioni e le connessioni vengono rallentate o interrotte. Il raggiungimento di un limite a livello hardware interessa tutti i database, e gli utenti, nel nodo fisico sottostante, causando l'interruzione delle operazioni esistenti e impedendo nuove operazioni o connessioni fino a quando il valore di soglia della limitazione della risorsa non si abbassa.

Alcune di queste limitazioni determinano limiti potenzialmente non intuitivi di progettazione e di prestazioni di un'applicazione. Ad esempio, se si limita l'aumento delle dimensioni del log delle transazioni fino a un massimo di 2 GB per transazione è possibile impedire la compilazione di un indice in una tabella di grandi dimensioni che comporta la generazione di un log delle transazioni di più di 2 GB. Le tecniche per eseguire operazioni di questo tipo vengono illustrate nella sezione "Procedure consigliate" di questo documento.

La gestione di questi tipi di condizioni di limitazione e di errori temporanei richiede un'attenta progettazione e l'implementazione del codice client. Per risolvere questi problemi è necessario eseguire la scalabilità orizzontale del livello del database in modo da poter utilizzare più database contemporaneamente. La scalabilità orizzontale verrà illustrata nella sezione successiva.

Tramite il codice dell'applicazione client SQL devono essere possibili le operazioni seguenti:

  • Implementazione del codice tentativi tramite cui vengono riconosciuti i codici di errore SQL correlati alla limitazione e grazie al quale si dispone di logica backoff appropriata. La mancanza di un modulo di logica backoff nell'applicazione può determinare il blocco del database in uno stato continuo di limitazione dovuto all'inserimento in modo costante di carichi massimi nel database.

  • Registrazione di errori di limitazione, utilizzando il codice tentativi per distinguere situazioni di connessione temporanea, limitazione, errori gravi, ad esempio di sintassi, nonché stored procedure mancanti e così via. In questo modo sarà possibile tenere traccia e risolvere i problemi di disponibilità dell'applicazione.

  • Implementazione di un modello di interruttore. In caso di scadenza di criteri di tentativi scelti in modo appropriato (bilanciamento della latenza e della risposta di sistema relativamente alla frequenza di esecuzione di tentativi da parte dell'applicazione), richiamare un percorso di codice per gestire gli errori non temporanei, in pratica attivare l'interruttore. Tramite il codice dell'applicazione saranno quindi possibili i risultati seguenti:

    • Fallback su un altro servizio o approccio. Se tramite l'applicazione non è possibile l'inserimento di nuovi dati nel database SQL, e l'immediata disponibilità di questi ultimi non è necessaria, i dati in questione potrebbero invece essere serializzati in una tabella di dati, o in un altro formato XML/JSON, ed essere scritti in un file nell'archiviazione BLOB. Tramite l'applicazione potrebbe quindi essere restituito un codice di operazione completata all'utente, o alla chiamata API, ed eseguire l'inserimento dei dati nel database in un passaggio successivo.

    • Esito negativo senza generazione di avviso restituendo un valore Null, se i dati o il flusso di lavoro sono facoltativi (non avranno un impatto sull'esperienza dell'utente finale).

    • Esito negativo rapido restituendo un codice di errore qualora non sia disponibile alcun meccanismo di fallback utile o appropriato.

Il database SQL può garantire con facilità un elevato numero di unità di scala (database) relativamente ridotte. Per implementare applicazioni altamente scalabile in Azure utilizzando il database SQL, è necessario un approccio con scalabilità orizzontale, componendo le risorse di più database in modo da poter soddisfare la domanda variabile. Con le applicazioni tradizionalmente indirizzate verso una sorta di "guscio d'uovo in titanio" di un singolo server database altamente resiliente con scalabilità verticale, è necessaria una progettazione attenta affinché nelle applicazioni il servizio del database con scalabilità orizzontale venga utilizzato in modo efficiente.

Con il database SQL, come con gli altri servizi di base di Azure, la scalabilità orizzontale e la composizione sono gli elementi chiave per scala (dimensioni database, velocità effettiva) e risorse (thread di lavoro e così via) aggiuntive. Sono disponibili due approcci di base per implementare il partizionamento, e quindi la scalabilità orizzontale, per il database SQL. Questi approcci non si escludono a vicenda in un'applicazione:

  • Partizionamento orizzontale. In un approccio di partizionamento orizzontale, le tabelle o i set di dati invariati vengono ripartiti in singoli database. Ad esempio, in caso di applicazione multi-tenant utilizzata da gruppi diversi di clienti, si possono creare, tramite l'applicazione, database per ogni cliente. In caso di applicazione single-tenant di grandi dimensioni, la tabella Customer può trovarsi in un database diverso rispetto alla tabella Orders. La chiave di partizionamento è in genere l'identificatore del tenant, ad esempio l'ID cliente. Nel diagramma seguente il set di dati è partizionato orizzontalmente in tre diversi database, utilizzando un hash di posta elettronica come valore di partizione, cioè la chiave di partizione è la posta elettronica e dalla funzione di partizione viene utilizzato un hash della chiave per eseguire il mapping a un database di destinazione.

  • Partizionamento verticale. In un approccio di partizionamento verticale, un set di dati viene distribuito tra più tabelle o database fisici, in base al partizionamento dello schema. Ad esempio, i dati sui clienti e quelli sugli ordini possono essere distribuiti tra database fisici diversi. Nel diagramma riportato di seguito il set di dati è partizionato verticalmente in due database diversi. Le informazioni principali relative all'utente (nome, posta elettronica) vengono archiviate in DB1, con le informazioni sul profilo utente (ad esempio l'URI dell'immagine avatar) archiviate in DB2.

In molte applicazioni verrà utilizzata una combinazione di partizionamento orizzontale e verticale (partizionamento ibrido), nonché l'inserimento di servizi di archiviazione aggiuntivi. Prendendo in considerazione l'esempio sopra indicato, le immagini avatar degli utenti sono state archiviate come ID nel database e verranno estese a URL completi dall'applicazione. Di questo URL verrà successivamente eseguito il mapping a un'immagine archiviata in un BLOB.

Quando si utilizza un archivio dati relazionale con scalabilità orizzontale, il calcolo di disponibilità è molto diverso. La probabilità che alcuni singoli segmenti dati, in sistemi con numeri elevati di partizioni, siano offline è più elevata rispetto alla possibilità di mancata disponibilità dell'intera applicazione. Nelle applicazioni potrebbe essere necessario tener conto della disponibilità parziale degli archivi dati back-end. Con un modello di dati con scalabilità orizzontale, la disponibilità dei dati non è più una condizione di tipo "tutto o niente".

La ripartizione dei dati può riverlarsi un'operazione complessa, specialmente in caso di modifica nel tempo del modello di utilizzo o della distribuzione dei dati. Per le chiavi di partizionamento basate su intervalli, a prescindere dal fatto che dipendano da un numero fisso (utilizzando un modulo hash dei valori di partizionamento) o dalla distribuzione dei valori di partizionamento, è necessario ribilanciare i dati tra singole partizioni. Negli schemi di partizione basati su intervalli vengono spesso utilizzate divisioni o unioni binarie per semplificare il ribilanciamento delle operazioni.

Ad esempio, i metodi di partizionamento a intervallo fisso, quale l'iniziale del cognome, possono essere avviati come distribuzione bilanciata. Tuttavia, questa operazione può diventare in fretta altamente sbilanciata nel momento in cui si presentano nuovi utenti, poiché ognuno possiede il proprio cognome che potrebbe eventualmente essere distribuito in modo uniforme nell'alfabeto. Si tenga presente la potenziale necessità nel tempo di modificare il meccanismo di partizionamento e il costo di ribilanciamento dei dati.

Gli schemi di partizionamento basati su ricerca sono più difficili da implementare e per essi è richiesto un meccanismo di ricerca a prestazioni elevate per ogni partizione o tenant di dati. Tuttavia, questi schemi risultano i più idonei per un ribilanciamento granulare, dal momento che consentono il ribilanciamento in modo distinto di un singolo tenant in una nuova partizione. Inoltre, grazie a questi schemi è possibile aggiungere ulteriore capacità (nuovi database e così via) al sistema senza dover copiare i dati.

Indipendentemente dalla combinazione di approcci di partizionamento, lo spostamento a una scalabilità orizzontale di database relazionali partizionati determina alcune restrizioni per le quali è richiesto un approccio diverso per la gestione dei dati e l'esecuzione di query:

  • Grazie alle valide progettazioni classiche riguardanti query e archiviazione dati SQL è stato possibile ottimizzare l'archiviazione e la coerenza sfruttando i modelli di dati altamente normalizzati. Questo approccio presuppone uno spazio dati coerente a livello globale, avvalendosi di riferimenti incrociati e di join tra tabelle. Con i nodi diffusi in nodi fisicamente distribuiti, i join e i riferimenti incrociati sono soluzioni accettabili solo in una singola partizione. Il database SQL non supporta query distribuite tra più database; l'unione di dati deve essere gestita a livello di client mentre la denormalizzazione e la replica di dati tra partizioni.

  • I metadati e i dati di riferimento vengono in genere centralizzati in tabelle di riferimento. In un approccio con scalabilità orizzontale, queste tabelle di riferimento, e i dati che non possono essere separati dalla chiave di partizionamento comune, devono essere replicati in partizioni e mantenuti coerenti.

  • Non esiste alcuna modalità concreta per garantire transazioni distribuite, ottimali a livello di prestazioni e scalabili in partizioni. Inoltre, i dati, e gli aggiornamenti di schemi, non saranno mai coerenti a livello transazionale tra le partizioni. Si deve presupporre e tener conto nel codice dell'applicazione di un livello non molto coerente tra le partizioni.

  • Per poter essere in grado di connettersi alle partizioni appropriate, è necessario comprendere il meccanismo di partizionamento (tipo di partizionamento verticale, orizzontale) del codice dell'applicazione.

  • Nel framework ORM comune (ad esempio Entity Framework) i modelli di dati con scalabilità orizzontale non vengono compresi a livello nativo. Per le applicazioni in cui è notevole l'utilizzo del framework ORM di grandi dimensioni potrebbe essere necessaria una riprogettazione significativa per soddisfare i requisiti di compatibilità con il partizionamento orizzontale. Per progettazioni in cui i tenant (gruppi di clienti) vengono isolati in un approccio partizionato verticalmente per un singolo database, è necessario un lavoro di riprogettazione meno impegnativo a livello di accesso ai dati. L'aspetto negativo che caratterizza il modello di partizionamento solo verticale è rappresentato dal fatto che ogni singola partizione è limitata dalla capacità di un singolo database.

  • Le query per le quali è necessario l'accesso (lettura o scrittura) a più partizioni devono essere implementate con un modello scatter-gather, in cui le singole query vengono eseguite sulle partizioni di destinazione, e con il set di risultati aggregato a livello di accesso ai dati del client.

La scalabilità orizzontale con il database SQL viene eseguita tramite il partizionamento manuale oppure orizzontale dei dati tra più database SQL. Questo approccio con scalabilità orizzontale offre l'opportunità di ottenere un aumento dei costi quasi lineare con la scala. La crescita o capacità elastica su richiesta può aumentare con costi incrementali in base alle esigenze. Non tutte le applicazioni sono in grado di supportare questo modello con scalabilità orizzontale senza una riprogettazione significativa.

  • Tramite gli aggiornamenti dello schema non viene garantita la coerenza a livello transazionale, specialmente quando si aggiorna un numero rilevante di partizioni. Nelle applicazioni si devono accettare eventuali periodi di inattività pianificati oppure si deve tener conto di più versioni simultanee dello schema distribuito.

  • Per i processi di continuità aziendale (backup e ripristino e così via) è opportuno tener conto di più partizioni di dati.

Le indicazioni e le procedure consigliate relative alla progettazione per la risoluzione di questi problemi verranno illustrate nella sezione "Procedure consigliate" in questo documento.

Nella rimanente parte di questo documento l'attenzione verrà posta sull'illustrazione delle procedure consigliate per ottenere applicazioni estremamente scalabili con Azure e il database SQL, in base alle esperienze reali e alle informazioni. In ogni procedura consigliata vengono descritti i componenti e l'ottimizzazione di destinazione, l'approccio di implementazione e i compromessi impliciti. Analogamente alle procedure consigliate, queste indicazioni hanno una stretta connessione con il contesto in cui vengono applicate. Valutare la validità di ogni procedura consigliata in base alle funzionalità della piattaforma illustrate nella sezione precedente.

noteNota
Le esperienze derivano dai tanti clienti che non si attengono al classico modello di elaborazione delle transazioni online (OLTP). È importante tener presente che alcune di queste procedure consigliate potrebbero non essere valide in caso di applicazioni per le quali si necessita di una coerenza assoluta dei dati. Solo l'utente conosce le reali esigenze aziendali dell'applicazione in uso e del relativo ambiente.

Ogni procedura consigliata sarà correlata a uno o più aspetti di ottimizzazione:

  • Velocità effettiva. Modalità di aumento del numero di operazioni (transazioni, chiamate al servizio e così via) tramite il sistema e di riduzione dei conflitti.

  • Latenza. Modalità di riduzione della latenza, sia in operazioni singole sia di aggregazione.

  • Densità. Modalità di riduzione dei punti di contesa durante la composizione dei servizi sia in contesti diretti, ad esempio il codice dell'applicazione nel database SQL, sia in contesti di aggregazione (utilizzo di più account di archiviazione per un aumento della scalabilità).

  • Facilità di gestione. Diagnostica, telemetria e visione complessiva della soluzione, vale a dire come comprendere l'integrità e le prestazioni dei servizi distribuiti nella scala.

  • Disponibilità. Modalità di aumento della disponibilità complessiva dell'applicazione riducendo l'impatto dei punti e delle modalità di errore (la disponibilità in base al carico viene fornita in base a velocità effettiva/latenza/densità).

Come l'unità di scala di base in Azure, una progettazione attenta e una distribuzione oculata dei servizi ospitati sono aspetti fondamentali per garantire servizi altamente scalabili e disponibili.

  • Il numero di istanze e di domini di aggiornamento all'interno di un servizio ospitato può influire in modo notevole sui tempi necessari per le fasi di distribuzione, configurazione e aggiornamento del servizio ospitato. Bilanciare i vantaggi offerti dalla scalabilità e dalle prestazioni con la maggiore complessità necessaria per ottenere questi benefici. Il miglioramento della scalabilità e della flessibilità comporta in genere l'aumento di costi di sviluppo e gestione di una soluzione.

  • Evitare i ruoli a istanza singola: con questa configurazione non vengono soddisfatti i requisiti del contratto di servizio di Azure. Durante un evento di aggiornamento o di errore del nodo, lo stato di un ruolo a istanza singola viene portato offline. Limitare il relativo utilizzo ad attività di manutenzione con priorità bassa.

  • A ogni data center viene assegnata una capacità che, per quanto ampia, è comunque limitata. Inoltre, in rare circostanze un data center può essere utilizzato come singolo punto di errore. Tramite i servizi per i quali viene richiesto il livello più alto di scalabilità e disponibilità deve essere implementata una topologia a più data center con più servizi ospitati. Tuttavia:

  • In caso di mancata necessità del livello più elevato di disponibilità (vedere voce precedente), verificare che le applicazioni e i servizi dipendenti siano completamente all'interno di un singolo data center. In situazioni in cui tramite la soluzione è necessario utilizzare più data center, attenersi alle linee guida seguenti:

    • Evitare chiamate di rete tra data center per le operazioni attive (eccetto la sincronizzazione intenzionale tra siti). La latenza lunga tra i data center può essere estremamente variabile e produrre caratteristiche di prestazioni dell'applicazione impreviste o indesiderate.

    • Disporre solo della funzionalità minima necessaria per l'accesso ai servizi in un altro data center. In genere, queste attività riguardano la continuità aziendale e la replica dei dati.

In caso di applicazioni distribuite su larga scala, l'accesso ai dati dell'applicazione con stato è un aspetto molto importante. La velocità effettiva e la latenza dell'applicazione complessiva sono in genere limitate dalla rapidità con la quale è possibile recuperare, partizionare e aggiornare il contesto e i dati richiesti. I servizi cache distribuiti, quali Azure Caching e memcached, sono stati ulteriormente sviluppati in risposta a questa esigenza. Nelle applicazioni è consigliabile l'utilizzo di una piattaforma cache distribuita. Tenere presenti le linee guida seguenti:

  • Utilizzare una piattaforma di memorizzazione nella cache distribuita come ruolo di lavoro all'interno del servizio ospitato. La prossimità ai client della cache consente di ridurre i limiti di latenza e di velocità effettiva presentati dall'attraversamento del bilanciamento del carico. Nella cache nel ruolo nella cache di Azure viene ospitata la memorizzazione nella cache in ruoli di lavoro in un servizio cloud.

  • Utilizzare la piattaforma di caching distribuito come repository primario per l'accesso agli oggetti e ai dati di applicazione comuni, ad esempio profilo utente e stato sessione, con supporto del database SQL o di un altro archivio durevole in un approccio read-through o cache-aside.

  • Gli oggetti della cache hanno una durata TTL (Time-to-Live) che influisce sul tempo in cui risultano attivi nella cache distribuita. Mediante le applicazioni la durata (TTL) viene impostata in modo esplicito sugli oggetti memorizzati nella cache oppure viene configurata una durata (TTL) predefinita per il contenitore della cache. Basare la scelta della durata (TTL) in base al rapporto esistente tra la disponibilità (riscontri nella cache) e le richieste di memoria e la semplicità dei dati.

  • Le cache presentano una semantica key->byte[]; tenere presente che l'uso di scritture sovrapposte può causare la creazione di dati incoerenti nella cache. Le cache distribuite in genere non forniscono un'API per gli aggiornamenti atomici dei dati archiviati, poiché non riconoscono la struttura dei dati archiviati.

    • Per le applicazioni che richiedono la coerenza assoluta delle scritture simultanee, utilizzare una piattaforma di caching di distribuzione in grado di fornire un meccanismo di blocco per l'aggiornamento delle entità. Nel caso di Azure Caching, può essere implementato tramite GetAndLock o PutAndUnlock. Nota: ciò avrà un impatto negativo sulla velocità effettiva.

  • Le prestazioni della cache sono limitate nel livello applicazione in base al tempo necessario per la serializzazione e la deserializzazione degli oggetti. Per ottimizzare questo processo, utilizzare un serializzatore binario ad elevata efficienza e relativamente simmetrico (che richiede lo stesso tempo necessario per la codifica e decodifica dei dati), quale protobuf.

    • Per utilizzare correttamente la serializzazione personalizzata, progettare oggetti DTO per la serializzazione nella cache, utilizzare l'annotazione appropriata per la serializzazione, evitare dipendenze cicliche e utilizzare unit test per tenere traccia della serializzazione efficiente.

Per impostazione predefinita, le connessioni tra i livelli di servizio, incluse le connessioni in ingresso tramite il bilanciamento del carico, sono soggette a uno schema di allocazione round robin, con blocco limitato delle connessioni. Nelle figure seguenti viene illustrato il mesh di connessione tipico risultante tra i livelli e i servizi esterni (a sinistra viene illustrata una tipica applicazione con il solo livello Web). Sebbene questo mesh non presenti problemi di prestazioni sostanziali per i protocolli di connessione leggeri, ad esempio HTTP, alcune connessioni sono dispendiose in termini di connessione/inizializzazione oppure rappresentano un risorsa gestita (limitata). Ad esempio, le connessioni al database SQL appartengono a questa categoria. Per ottimizzare l'utilizzo dei componenti e dei servizi esterni, è consigliabile creare affinità tra le chiamate delle risorse e istanze specifiche.

Nella figura precedente, la topologia a destra presenta livelli Web e di lavoro distinti (ruoli) all'interno dello stesso servizio ospitato. Questa topologia presenta inoltre affinità implementata tra i livelli Web e applicazione al fine di bloccare le chiamate da istanze specifiche dell'applicazione in scenari specifici. Ad esempio, per la richiesta di dati dal database 1 (DB1), è necessario che le istanze Web richiedano i dati tramite le istanze dell'applicazione numero uno o due. Poiché tramite il bilanciamento del carico di Azure viene attualmente implementata solo una tecnica round robin, la disponibilità dell'affinità nell'applicazione richiede una particolare attenzione in fase di progettazione e implementazione.

  • Progettare l'applicazione con livelli Web e applicazione separati, fornendo affinità dipendente dalla partizione e dalla risorsa tra il livello Web e applicazione.

  • Implementare la logica di routing che instrada in modo trasparente le chiamate interne al servizio a un'istanza dell'applicazione di destinazione. Utilizzare le informazioni del meccanismo di partizionamento utilizzato dalle risorse esterne o a valle, ad esempio il database SQL.

L'implementazione pratica di questa architettura a più livelli richiede una comunicazione dei servizi molto efficiente tra i livelli Web e applicazione, mediante l'utilizzo di protocolli leggeri ed efficaci.

Le tecniche di sviluppo di un'applicazione Azure non sono molto diverse dalle tecniche di sviluppo di Windows Server. Tuttavia, la flessibilità dell'infrastruttura evidenzia la necessità e il vantaggio dell'utilizzo di codice efficiente che utilizza le risorse di calcolo con la massima efficacia.

  • Presupporre che tutti i servizi, tutte le chiamate di rete e le risorse dipendenti siano potenzialmente non affidabili e soggette a modalità di errore temporanee e continue (un esempio di modalità di implementazione della logica di tentativi per il database SQL viene illustrato più avanti in questo argomento):

    • Implementare criteri di tentativi appropriati per tutte le chiamate ai servizi (database SQL, archiviazione e così via) per gestire le condizioni di errore temporanee e la perdita di connettività.

    • Implementare criteri backoff nella logica di tentativi per evitare rallentamenti (prolungamento delle interruzioni causato da un accumulo di tentativi nel servizio).

    • Implementare la telemetria avanzata lato client per registrare i messaggi e gli eventi di errore insieme alle informazioni contestuali (servizio di destinazione, contesto utente/account, attività e così via).

  • Non creare direttamente thread per la pianificazione del lavoro, ma utilizzare un framework di concorrenza e pianificazione, quale .NET Task Parallel Library. I thread sono oggetti relativamente pesanti e non sono semplici da creare ed eliminare. Le utilità di pianificazione che funzionano con un pool di thread condiviso sono in grado di pianificare ed eseguire il lavoro in modo più efficiente. Questa architettura fornisce inoltre una semantica di livello superiore per la descrizione della gestione degli errori e della continuazione.

  • Ottimizzare oggetti DTO (Data Transfer Object, oggetto di trasferimento dati) per la serializzazione e la trasmissione di rete. A causa dell'elevata distribuzione delle applicazioni Azure, la scalabilità dipende dal livello di efficienza con cui i singoli componenti del sistema sono in grado di comunicare nella rete. Per i dati passati nella rete ai fini della comunicazione o dell'archiviazione è richiesta l'implementazione della serializzazione del testo JSON o di un formato binario più efficiente con hint appropriati per ridurre al minimo la quantità di metadati trasferiti nella rete, ad esempio nomi di campo più brevi "in transito".

    • Se l'interoperatività rappresenta un fattore importante, utilizzare un formato testuale efficiente, ad esempio JSON per i metadati di interoperabilità e banda.

    • Se una velocità effettiva più elevata rappresenta un fattore importante, ad esempio nelle comunicazioni da servizio a servizio in cui si controllano entrambe le estremità, considerare un formato binario compresso ad elevata efficienza, ad esempio bson o protobuf.

      • Evitare un trasferimento dati "frammentato" (frequente) per gli oggetti di piccole dimensioni. Le comunicazioni "frammentate" tra servizi richiedono un eccessivo utilizzo di risorse di sistema fondamentali per l'esecuzione di attività di overhead ed sono soggetta a risposte con latenza variabile.

      • I test per la serializzazione e la deserializzazione degli oggetti devono rappresentare un componente principale del framework di test automatico. Il test delle funzionalità garantisce che le classi di dati siano serializzabili e che non siano presenti dipendenze cicliche. Il test delle prestazioni verifica i tempi di latenza richiesti e le dimensioni di codifica.

  • Se possibile, utilizzare framework leggeri per la comunicazione tra componenti e servizi. Numerose tecnologie tradizionali nello stack .NET forniscono un ampio set di funzionalità che potrebbe non essere allineato con la natura distribuita di Azure. I componenti che forniscono un elevato livello di astrazione tra finalità ed esecuzione implicano spesso costi elevati in termini di prestazioni.

    • Se il supporto di protocolli avanzati o dell'interoperatività tra protocolli non è richiesto, valutare la possibilità di utilizzare l'API Web ASP.NET anziché WCF per l'implementazione dei servizi Web.

    • Se le funzionalità avanzate di Entity Framework non sono richieste, valutare la possibilità di utilizzare un prodotto ORM micro, quale Dapper, per implementare il livello client SQL.

  • Ridurre la quantità di dati rilasciati dal data center abilitando la compressione HTTP in IIS per i dati in uscita.

  • Creare l'affinità delle connessioni tra i livelli per ridurre la "frammentarietà" (frequenza) e il cambio di contesto delle connessioni.

  • Per ridurre il carico sull'applicazione, utilizzare l'archiviazione BLOB per il contenuto statico di dimensioni più elevate (> 100 KB).

  • Per ridurre il carico sull'applicazione, utilizzare la rete CDN tramite l'archiviazione BLOB per il contenuto statico, ad esempio immagini o CSS.

  • Evitare di utilizzare il database SQL per i dati della sessione. Utilizzare invece la cache distribuita o i cookie.

Archiviazione di Azure rappresenta la backbone dei dati durevoli in un'applicazione Azure. Pur fornendo un'esperienza altamente affidabile e scalabile, per le applicazioni su larga scala sono necessarie linee guide di utilizzo e progettazione appropriate.

  • Utilizzare più account di archiviazione per ottenere una maggiore scalabilità. Ciò consente un aumento delle dimensioni (> 100 TB) o un aumento della velocità effettiva (> 5.000 operazioni al secondo). Assicurarsi che il codice dell'applicazione possa essere configurato per l'utilizzo di più account di archiviazione, con funzioni di partizionamento appropriate per il routing del lavoro agli account di archiviazione. Progettare la capacità di aggiungere ulteriori account di archiviazione come una modifica della configurazione, anziché del codice.

  • Selezionare con attenzione le funzioni di partizionamento per l'archiviazione tabelle, al fine di abilitare la scalabilità desiderata in termini di prestazioni delle query e inserimento. Prendere in considerazione l'approccio di partizionamento basato sul tempo per i dati di telemetria, con chiavi composte basate sui dati di riga per i dati non temporali. Mantenere le partizioni in un intervallo appropriato al fine di ottenere prestazioni ottimali; le partizioni di dimensioni particolarmente ridotte limitano la possibilità di eseguire operazioni batch (inclusa l'esecuzione di query), mentre le partizioni di dimensioni molto elevate risultano più costose da sottoporre a query e possono creare colli di bottiglia in caso di inserimenti con volumi elevati simultanei.

    • La scelta della funzione di partizionamento avrà inoltre un notevole impatto sulle prestazioni delle query. L'archiviazione delle tabelle consente la ricerca efficiente per {chiave di partizione, chiave di riga}, con un'elaborazione meno efficiente di {chiave di partizione, filtro delle corrispondenze delle righe} e {filtro delle corrispondenze delle chiavi di partizione, filtro delle corrispondenze delle chiavi di riga}. Mediante le query che richiedono una tabella globale viene eseguita l'analisi del ({filtro delle corrispondenze delle chiavi di riga}).

    • Le partizioni possono essere ridotte come una singola entità. Ciò fornisce prestazioni estremamente ottimizzate per i semplici carichi di lavoro di ricerca, quali la gestione del carrello acquisti.

  • Se possibile, inviare le operazioni in batch nell'archiviazione. Le scritture nelle tabelle devono essere eseguite in batch, in genere tramite l'utilizzo del metodo SaveChanges nell'API client .NET. Inserire una serie di righe in una tabella, quindi eseguire il commit delle modifiche in un singolo batch con il metodo SaveChanges. Anche gli aggiornamenti all'archiviazione BLOB devono essere sottoposti a commit nel batch, utilizzando il metodo PutBlockList. Come con l'API di archiviazione delle tabelle, chiamare PutBlockList su un intervallo di blocchi, anziché su singoli blocchi.

  • Scegliere nomi di colonna brevi per le proprietà della tabella; analogamente ai metadati (nomi delle proprietà) sono archiviati in banda. Anche i nomi delle colonne sono inclusi nel conteggio delle dimensioni di riga massime, pari a 1 MB. I nomi di proprietà eccessivamente lunghi causano un elevato utilizzo delle risorse di sistema.

Come illustrato nella sezione relativa all'esplorazione di Azure, il database SQL offre database relazionali chiavi in mano come funzionalità del servizio, consentendo un accesso scalabile all'archiviazione dati, sotto forma di scalabilità orizzontale. Ai fini del corretto utilizzo del database SQL nelle applicazioni su larga scala, è necessario effettuare con attenzione varie scelte di pianificazione e implementazione. In questa sezione vengono delineati i punti chiave relativi alla pianificazione e vengono indicate le procedure consigliate.

Per molte applicazioni è necessaria una tabella di metadati per archiviare dettagli quali informazioni relative al routing, al partizionamento e al tenant. L'archiviazione di questi metadati in un singolo database implica la creazione di un singolo punto di errore e un collo di bottiglia per la scalabilità. La scalabilità orizzontale per gli archivi di metadati centrali deve essere eseguita tramite una combinazione dei fattori riportati di seguito.

  • Caching ripetuto. Per le informazioni nel database di configurazione deve essere ripetutamente eseguita la memorizzazione in una cache distribuita, quale memcached o Azure Caching.

    • Tenere presente l'effetto dei ripetuti tentativi di precaricare la cache da più thread di lavoro all'avvio dell'applicazione, che in genere conducono a un eccessivo carico e alla limitazione del database. Se l'applicazione richiede una cache precaricata, delegare la responsabilità del caricamento dei dati a un ruolo di lavoro dedicato (o un'attività pianificata) con una percentuale di carico configurabile.

    • Se le prestazioni o l'affidabilità dell'applicazione dipende dalla disponibilità di un determinato segmento di dati nella cache, è necessario che l'applicazione rifiuti le richieste in arrivo finché la cache non sia stata prepopolata. Durante il popolamento dei dati, l'applicazione deve restituire un messaggio o un codice di errore appropriato.

  • Scalabilità orizzontale. Partizionare i dati in verticale (per tabella) o in orizzontale (segmentazione della tabella tra più partizioni) per ripartire il carico su più database.

La scalabilità complessiva di un database SQL partizionato è limitata dalla scalabilità di un singolo database (partizione) e dall'efficienza con cui tali partizioni possono essere combinate per ottenere un aumento delle scalabilità:

  • Poiché i limiti del log delle transazioni limitano le transazioni di dimensioni maggiori, ad esempio la ricompilazione degli indici, le singole tabelle non devono essere superiori a circa 10 GB. Tenere presente che questo limite pratico dipende dalle dimensioni degli indici della tabella di destinazione. Potrebbe pertanto essere maggiore o minore di 10 GB per il database in uso. Per le singole tabelle di grandi dimensioni, suddividere la tabella in singole tabelle più piccole e utilizzare una vista partizionata per fornire una sovrapposizione uniforme.

    • Mantenendo ridotte le dimensioni delle singole tabelle, si riduce l'impatto della modifica di uno schema o della ricompilazione di un indice durante un aggiornamento a fasi. Le modifiche apportate a più tabelle di piccole dimensioni riducono al minimo il tempo di inattività e la latenza dovuta alle operazioni di blocco.

    • Tale partizionamento rende più complesse le tecniche di gestione. Operazioni quali la ricompilazione dell'indice devono essere eseguite in modo iterativo su tutte le tabelle del componente.

  • Mantenere il più possibile ridotte le dimensioni dei singoli database (partizioni). Il completamento di operazioni di continuità, quali la copia di database o le esportazioni, eseguite su database con dimensioni maggiori di 50 GB può richiedere diverse ore. Tenere presente che le operazioni eseguite per più di 24 ore vengono annullate dal servizio.

In un mondo in cui la continuità dei servizi è fondamentale, è opportuno gestire con particolare cura e attenzione gli aggiornamenti dei database distribuiti o le modifiche degli schemi, al fine di garantirne un'esecuzione priva di problemi. Tutte le procedure consigliate tradizionali per il controllo delle operazioni sui metadati e sugli schemi in un archivio dati di produzione hanno un'importanza senza precedenti. Ad esempio, un'operazione di debug e risoluzione relativa a una stored procedure eliminata in modo accidentale risulta molto più complessa se seguita su 100 database, anziché su 1.

Poiché gli aggiornamenti degli schemi e le modifiche dei dati non sono coerenti dal punto di vista transazionale all'interno delle partizioni, gli aggiornamenti dell'applicazione devono essere compatibili sia con i nuovi schemi che con quelli precedenti durante il periodo di transizione. In base a questo requisito, ogni versione dell'applicazione deve in genere essere compatibile almeno con la versione corrente e la versione precedente dello schema.

Il passaggio a una raccolta con scalabilità orizzontale dei database crea problemi per la gestione delle connessioni. Ogni connessione al database SQL è una risorsa relativamente dispendiosa, come si evince dall'utilizzo esteso del pool di connessioni nelle API client (ADO.NET, ODBC, PHP e così via). Anziché gestire più connessioni a un'istanza di SQL Server centrale, ogni istanza dell'applicazione deve poter gestire connessioni a più server di database.

Poiché le connessioni rappresentano una risorsa dispendiosa e potenzialmente limitata, le applicazioni devono gestire correttamente le connessioni restituendo le connessioni in pool in modo tempestivo. È necessario che il codice dell'applicazione utilizzi l'eliminazione automatica delle connessioni. In .NET è consigliabile eseguire il wrapping di tutte le occorrenze di SqlConnection all'interno di un'istruzione using, ad esempio:

using (var conn = new SqlConnection(connStr))
{
    // SQL client calls here
}

Come descritto in precedenza, le connessioni a un database SQL sono soggette a errori di connessione temporanei. La logica di tentativi deve essere utilizzata per tutte le connessioni e tutti i comandi che si desidera proteggere da tali errori temporanei. Di seguito sono disponibili ulteriori dettagli.

Il database SQL supporta solo le connessioni TCP (non named pipe). È inoltre consigliabile crittografare la connessione tra il codice dell'applicazione e il database SQL. Per evitare tentativi di connessione imprevisti (ad esempio tentativi di utilizzo delle named pipe) è necessario che alle stringhe di connessione SQL delle applicazioni venga applicato il seguente formato:

Server=tcp:{servername}.database.windows.net,1433;Database={database};User ID={userid}@{database};Password={password};Trusted_Connection=False;Encrypt=True;Connection Timeout=30;

Per le distribuzioni di applicazioni su larga scala, il numero predefinito di potenziali connessioni può aumentare in modo esponenziale tra una distribuzione di servizio ospitato e i server logici del database SQL in un cluster di database SQL (ognuno dei quali dispone di un singolo indirizzo IP esterno). Prendere ad esempio in considerazione un servizio ospitato con 100 istanze, 50 database e il numero predefinito di connessioni, ovvero 100 connessioni per impostazione predefinita in ADO.NET.

MaxConnections=DatabaseCount*Instance Count*MaxConnectionPoolSize

Fare riferimento alla topologia di rete per un servizio ospitato. Ogni lato della connessione (il servizio ospitato e i server logici del database SQL) è attivo in un sevizio di bilanciamento del carico di Azure. . Ogni servizio di bilanciamento del carico di Azure ha un limite massimo di 64000 connessioni tra due indirizzi IPv4. La combinazione di questa topologia di rete con il numero predefinito di connessioni disponibili comporta gravi errori di rete per le applicazioni di grandi dimensioni.

  • Distribuire le applicazioni di dimensioni maggiori tra più servizi ospitati.

  • Distribuire i database in più sottoscrizioni (non solo più server logici nella stessa sottoscrizione) per ottenere più indirizzi IP univoci.

  • Implementare applicazioni a più livelli per creare affinità tra le operazioni in uscita in un'istanza dell'applicazione di destinazione (vedere la sezione precedente sui servizi ospitati).

  • Tenere presente che i pool di connessioni vengono gestiti per ogni stringa di connessione univoca e corrispondono a ogni combinazione univoca di server di database, database e account di accesso. Utilizzare il pool di connessioni client SQL e limitare in modo esplicito le dimensioni massime del pool di connessioni SQL. Le librerie client SQL riutilizzano le connessioni in base alle necessità; un pool di connessioni di piccole dimensioni può causare un aumento della latenza durante l'attesa da parte delle applicazioni della disponibilità delle connessioni.

Nell'elenco seguente vengono forniti consigli per ridurre il numero delle connessioni attive richieste:

Il passaggio a un modello di dati distribuito può richiedere modifiche alla progettazione dello schema del database e a determinati tipi di query. È probabile che le applicazioni che richiedono l'utilizzo di transazioni distribuite su più database dispongano di un modello di dati o di un'implementazione non appropriati, ad esempio a causa del tentativo di imporre una coerenza complessiva. È necessario eseguire il refactoring di tali progettazioni.

È necessario evitare di utilizzare una funzionalità di generazione delle sequenze centrale per aspetti complessi dell'applicazione, a causa dei vincoli di scalabilità e disponibilità. In molte applicazioni le sequenze vengono utilizzate per rendere disponibili identificatori univoci globali (GUID), utilizzando un meccanismo di rilevamento centrale per incrementare la sequenza su richiesta. Mediante questa architettura vengono generati un punto di contesa e un collo di bottiglia a livello globale, con cui ogni componente del sistema deve interagire. Tale collo di bottiglia rappresenta un problema in particolare per le applicazioni mobili eventualmente disconnesse.

Nelle applicazioni devono invece essere utilizzate funzioni in grado di generare identificatori univoci globali, ad esempio GUID, in un sistema distribuito. In base alle caratteristiche di progettazione, i GUID non sono sequenziali e possono pertanto provocare la frammentazione se utilizzati come un INDICE CLUSTER in una tabella di dimensioni elevate. Per ridurre l'impatto della frammentazione dei GUID in un modello di dati di dimensioni elevate, suddividere il database in partizioni, mantenendo dimensioni relativamente ridotte per le singole partizioni. In questo modo, tramite il database SQL viene eseguita automaticamente la deframmentazione dei database in uso durante il failover della replica.

È necessario che nel codice dell'applicazione client vengano presi in considerazione vari aspetti correlati recapito di un modello di dati distribuito:

  • Chiavi di partizione. Le chiavi di partizione devono far parte di ogni modello o classe di dati e potrebbero essere associate a un attributo che ne consente l'individuazione.

  • Telemetria. Il livello di accesso ai dati deve automaticamente registrare informazioni su ogni chiamata SQL, tra cui la destinazione, la partizione, il contesto, la latenza e qualsiasi tentativo o codice di errore.

  • Query distribuite. L'esecuzione di query tra partizioni introduce molte nuove problematiche, tra cui il routing, la selezione delle partizioni e il concetto di esito positivo parziale, che implica la corretta restituzione di dati solo da parte di alcune singole partizioni e non altre. Il livello di accesso ai dati deve fornire i delegati per l'esecuzione di query distribuite in un modo scatter-gather (parallelo) asincrono, per la restituzione di un risultato composito. Per le query distribuite deve inoltre essere presa in considerazione la limitazione delle risorse sottostanti:

    • Massimo grado di parallelismo (per evitare un elevato utilizzo di connessioni e thread).

    • Durata massima delle query (per ridurre il riscontro complessivo della latenza da una query con esecuzione prolungata o una partizione lenta).

Esistono inoltre numerose attività di gestione in sospeso che devono essere eseguite:

  • Tabelle di riferimento. Senza uno spazio di query coerente a livello globale, i dati di riferimento per i JOIN nelle query devono essere copiati in ciascuna singola partizione. La gestione dei dati e la relativa replica nelle tabelle di riferimento delle singole partizioni sono necessarie per fornire dati di riferimento locali abbastanza coerenti.

  • Ribilanciamento delle partizioni. È possibile che le singole partizioni non risultino bilanciate, ad esempio utilizzano troppe risorse e rappresentano pertanto un blocco oppure vengono utilizzate in modo insufficiente e implicano un inutile consumo di risorse. In queste situazioni, è necessario bilanciare di nuovo le partizioni per riallocare le risorse. Il meccanismo di ribilanciamento dipende notevolmente dalla strategia e dall'implementazione del partizionamento. Nella maggior parte degli scenari il ribilanciamento implica in genere quanto segue:

    • Copia di dati di una partizione in una o più nuove partizioni, tramite il meccanismo di suddivisione/unione (per il partizionamento basato su intervalli) o la copia a livello di entità e la modifica del mapping (per il partizionamento basato su ricerca).

    • Aggiornamento del mapping della partizione affinché punti alla nuova partizione e successiva compensazione per i dati scritti nelle partizioni precedenti durante la transizione.

  • Eliminazione di dati. Man mano che le dimensioni di un'applicazione aumentano e viene effettuata la raccolta dei dati, prendere in considerazione la possibilità di eliminare periodicamente dati meno recenti non utilizzati, anziché aumentare la capacità aggiuntiva e lo spazio del sistema primario. I dati eliminati non vengono eliminati in modo sincrono dal database SQL, ma vengono contrassegnati per l'eliminazione e puliti tramite un processo in background. Un metodo comune per contrassegnare i dati per l'eliminazione è rappresentato da una colonna in cui una riga può essere segnalata come attiva, inattiva o contrassegnata per l'eliminazione. In questo modo è possibile mascherare i dati per escluderli dalle query per un periodo di tempo specifico, consentendone lo spostamento in produzione con facilità, qualora vengano segnalati come necessari dagli utenti.

    L'eliminazione dei dati può inoltre generare la frammentazione, rendendo probabilmente necessaria la ricompilazione di un indice per eseguire operazioni di query più efficienti. I dati meno recenti possono essere archiviati nelle seguenti posizioni:

    • Un archivio online (database SQL secondario). Ciò consente di aumentare la capacità aggiuntiva nel sistema primario, ma non di ridurre i costi.

    • Un archivio offline, ad esempio un file con estensione bcp o bacpac nell'archiviazione BLOB. Ciò consente di aumentare la capacità aggiuntiva nel sistema primario e di ridurre i costi.

    • Il bucket di bit. È possibile scegliere di eliminare i dati dal sistema primario in modo permanente per aumentare la capacità aggiuntiva.

Numerose occorrenze comuni nel database SQL possono generare errori di connessione temporanei, ad esempio il failover della replica. Nelle applicazioni deve essere implementato il codice appropriato per gestire gli errori temporanei e rispondere correttamente all'esaurimento e alla limitazione delle risorse:

  • Gestione degli errori di connessione temporanei con nuovi tentativi. Il codice di accesso ai dati deve utilizzare un meccanismo di tentativi basato su criteri per la compensazione degli errori di connessione temporanei. Il meccanismo di tentativi deve rilevare gli errori di connessione temporanei, eseguire di nuovo la connessione al database SQL di destinazione e rieseguire il comando.

  • Gestione della limitazione con la logica di tentativi e di backoff. Il codice di accesso ai dati deve utilizzare un meccanismo di tentativi e backoff basato su criteri per la gestione delle condizioni di limitazione. Il meccanismo di tentativi deve rilevare la limitazione e effettuare tentativi di backoff graduali per eseguire di nuovo il comando, al fine di evitare rallentamenti che potrebbero prolungare la condizione di limitazione.

    • Il codice di accesso ai dati deve inoltre implementare la possibilità di eseguire il backoff in un archivio dati alternativo, ad esempio l'archiviazione BLOB. Questo archivio alternativo fornisce un meccanismo durevole per l'acquisizione di attività, dati e stato, evitando la perdita di dati in caso di un evento di disponibilità e limitazione prolungata.

Le applicazioni .NET possono utilizzare i framework della logica di backoff e di tentativi dipendenti dal database SQL, ad esempio Cloud Application Framework (CloudFx) o Enterprise Library Transient Fault Handler. Questi framework rendono disponibili wrapper per le classi di accesso ai dati comuni (ad esempio, SqlConnection e SqlCommand) e criteri che è possibile richiamare in modo diretto.

var retryPolicy = RetryPolicy.Create<SqlAzureTransientErrorDetectionStrategy>(
    retryCount: 3, 
    initialInterval: TimeSpan.FromSeconds(5),
    increment: TimeSpan.FromSeconds(2));
                
using (var conn = new ReliableSqlConnection(connStr))
{
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {

    }
    conn.Close();
}

Il frammento di codice precedente illustra l'utilizzo della classe CloudFx ReliableSqlConnection per la gestione degli errori di connessione temporanei durante l'utilizzo del database SQL.

È opportuno prestare particolare attenzione alla registrazione di chiamate API nei servizi, ad esempio il database SQL, con modalità di errore potenzialmente complesse. Tentare di acquisire parti principali del contesto e delle informazioni sulle prestazioni. Ad esempio, tutte le sessioni del database SQL hanno un identificatore di sessione che può essere utilizzato per le chiamate di supporto al fine di isolare direttamente il problema sottostante. È consigliabile che per ogni chiamata, comando e query nel database SQL venga registrato quanto segue:

  • Nome di database e server. Con circa centinaia di database, il server di destinazione è molto importante ai fini del rilevamento e dell'isolamento dei problemi.

  • A seconda dei casi, la stored procedure SQL o il testo del comando. Fare attenzione a non includere informazioni sensibili nel file di log. Evitare in genere di registrare il testo del comando.

  • La latenza end-to-end della chiamata. Eseguire il wrapping della chiamata in un delegato di temporizzazione, tramite cronometro o un altro timer leggero.

  • Il codice del risultato della chiamata (esito positivo o negativo), il numero di tentativi e la causa dell'errore (connessione eliminata, limitata e così via).

  • L'ID di sessione della connessione, accessibile tramite la proprietà CONTEXT_INFO() o tramite la proprietà SessionTracingId se si utilizza ReliableSqlConnection. Tuttavia, non è possibile recuperare la proprietà dell'ID di sessione da CONTEXT_INFO() in ogni chiamata client, in quanto questo comando genera un altro round trip del server.

Per un utilizzo più efficiente del database SQL, è necessario che le query e gli inserimenti di dati sul database SQL vengano eseguiti in batch ed in modo asincrono, se possibile. Ciò non implica solo il miglioramento dell'efficienza dell'applicazione, ma riduce anche il carico del sistema complessivo sul database SQL (garantendo una velocità effettiva più elevata).

  • Inserimento in batch. Per le operazioni di inserimento di dati continue, ad esempio la registrazione di nuovi utenti, i dati devono essere inviati in batch e allineati nelle partizioni di destinazione. Questi batch devono essere scritti periodicamente e in modo asincrono nel database SQL in base a trigger, ad esempio le dimensioni del batch di destinazione o una finestra temporale. Per dimensioni di batch inferiori a 100 righe, le funzioni con valori di tabella sono in genere più efficienti rispetto alla copia bulk.

  • Evitare interfacce "frammentate". Ridurre il numero di round trip richiesti nel database per eseguire una query o un set di operazioni. Le interfacce "frammentate" dispongono di un elevato livello di overhead, che aumenta il carico sul sistema, riducendo la velocità effettiva e l'efficienza. Tentare di unire le operazioni correlate, in genere tramite una stored procedure per ridurre il numero di round trip.

Come parte di un approccio complessivo di continuità aziendale, i dati archiviati nel database SQL devono essere esportati periodicamente nell'archiviazione BLOB. Per impostazione predefinita, l'archiviazione BLOB supporta la disponibilità e la replica geografica.

Implementare un'attività pianificata mediante la quale i database vengono esportati periodicamente nell'archiviazione BLOB. Utilizzare un account di archiviazione dedicato. Questa attività deve essere eseguita nello stesso data center del database di destinazione, non da un desktop o server locale.

Pianificare l'attività di esportazione per le ore di minore attività, al fine di ridurre al minimo l'impatto sull'esperienza dell'utente finale. Quando si esportano più database, limitare il livello di esportazione parallela per ridurre l'impatto sul sistema.

La conoscenza dell'integrità, delle prestazioni e della capacità aggiuntiva dei database SQL è un componente fondamentale ai fini della disponibilità complessiva dei servizi. Il database SQL offre le informazioni non elaborate necessarie tramite DMV (viste a gestione dinamica), ma non è attualmente disponibile un'infrastruttura chiavi in mano per acquisire, analizzare e creare metriche chiave. Per rendere questa funzionalità disponibile per il database SQL, tenere presenti le seguenti procedure:

  • Implementare un'attività periodica per raccogliere i dati delle prestazioni chiave relativi al carico di sistema, alle risorse utilizzate (thread di lavoro, spazio di archiviazione) e ai dati in un repository comune. Prendere ad esempio in considerazione le tabelle utilizzate in Diagnostica Azure. È necessario che mediante questa attività vengano raccolti i dati di tutti i database che appartengono all'applicazione. Questa raccolta si verifica in genere in base alla scalabilità orizzontale, ovvero mediante la raccolta dei dati da più database contemporaneamente.

  • Implementare un'attività periodica per aggregare tali informazioni e compilare gli indicatori di prestazioni chiave (KPI) dell'integrità e dalla capacità dei database distribuiti.

Diagnostica Azure rappresenta lo strumento di base per la raccolta della telemetria a livello di istanza e applicazione. Tuttavia, per fornire informazioni sulle applicazioni su larga scala che eseguono Azure è necessario configurare e gestire con particolare attenzione i flussi di dati. Diversamente dalle applicazioni centralizzate con scalabilità verticale che supportano l'utilizzo delle utilità di diagnostica avanzate di Windows, in un sistema distribuito con scalabilità orizzontale è necessario effettuare le operazioni di diagnostica prima dell'attivazione del sistema. Non è possibile eseguire tali operazioni in un momento successivo.

La gestione degli errori, la traccia contestuale e l'acquisizione telemetrica sono fondamentali per fornire informazioni sugli eventi di errore, sulle relative cause principali e sulle risoluzioni.

  • Non pubblicare i dati e la telemetria del sito nello stesso account di archiviazione. Utilizzare un account di archiviazione dedicato per la diagnostica.

  • Creare canali separati per la telemetria "voluminosa" (volume elevato, latenza elevata, dati granulari) e "frammentata" (volume ridotto, latenza ridotta, dati di valore elevato).

    • Utilizzare origini di Diagnostica Azure standard, ad esempio tracce e contatori delle prestazioni, per le informazioni "frammentate".

    • Utilizzare librerie di registrazione comuni, ad esempio Enterprise Application Framework Library, log4net o NLog, per implementare la registrazione delle informazioni bulk in file locali. Utilizzare un'origine dati personalizzata nella configurazione del monitor di diagnostica per copiare periodicamente tali informazioni nell'archiviazione BLOB.

  • Registrare tutte le chiamate API in servizi esterni unitamente a contesto, destinazione, metodo, informazioni sui tempi (latenza) e risultato (esito positivo/errore o tentativi). Utilizzare il canale di registrazione "voluminoso" per evitare di sovraccaricare il sistema di diagnostica con le informazioni di telemetria.

  • I dati scritti nell'archiviazione delle tabelle (contatori delle prestazioni, log eventi, eventi di traccia) vengono scritti in una dimensione temporale di 60 secondi. Se si tenta di scrivere una quantità eccessiva di dati (troppe origini puntiformi, per un intervallo di raccolta troppo ridotto), potrebbe verificarsi un sovraccarico della partizione. Verificare che i picchi di errore non generino un tentativo di inserimento di volumi elevati nell'archiviazione delle tabelle, in quanto ciò potrebbe generare un evento di limitazione.

    • Scegliere dati di valore elevato per la raccolta da tali origini, tra cui contatori delle prestazioni chiave, eventi di errore/critici o record di traccia.

    • Selezionare un intervallo di raccolta appropriato (da 5 a 15 minuti) per ridurre la quantità di dati da trasferire e analizzare.

  • Verificare che la configurazione di registrazione possa essere modificata in fase di esecuzione senza la necessità di forzare reimpostazioni dell'istanza. Verificare inoltre che la configurazione sia abbastanza granulare da consentire la registrazione di aspetti specifici del sistema, quali database, cache o altri servizi.

Diagnostica Azure non supporta la raccolta dati per i servizi dipendenti, ad esempio un database SQL o una cache distribuita. Per una visione completa dell'applicazione e delle relative caratteristiche in termini di prestazioni, aggiungere l'infrastruttura per la raccolta dei dati per i servizi dipendenti:

  • Raccogliere i dati di utilizzo e delle prestazioni chiave dai servizi dipendenti e pubblicarli nel repository WAD come record del contatore delle prestazioni.

    • Archiviazione Azure tramite l'analisi dell'archiviazione Azure.

    • Database SQL tramite DMV.

    • Cache distribuita tramite i contatori delle prestazioni o le API di monitoraggio dell'integrità.

  • Analizzare periodicamente i dati di telemetria non elaborati per creare aggregazioni e rollup (ad esempio un'attività pianificata).

Mostra:
© 2014 Microsoft