Modello di app Web affidabile per .NET

Servizio app di Azure
Frontdoor di Azure
Cache di Azure per Redis
.NET

Questo articolo fornisce indicazioni sull'implementazione del modello di app Web Reliable. Questo modello illustra come modificare (ripiattaforma) le app Web per la migrazione cloud. Offre un'architettura prescrittiva, codice e linee guida di configurazione allineate ai principi di Well-Architected Framework.

Perché il modello Reliable Web App per .NET?

Il modello Reliable Web App è un set di principi e tecniche di implementazione che definiscono come riformare le app Web durante la migrazione al cloud. È incentrato sugli aggiornamenti minimi del codice che è necessario apportare per avere successo nel cloud. Le indicazioni seguenti usano l'implementazione di riferimento come esempio in tutto e seguono il percorso di ripiattaforma dell'azienda fittizia, Relecloud, per fornire il contesto aziendale per il percorso. Prima di implementare il modello Reliable Web App per .NET, Relecloud aveva un'app Web di ticketing locale monolitica che usava il framework di ASP.NET.

Suggerimento

Logo di GitHubÈ disponibile un'implementazione di riferimento (esempio) del modello Reliable Web App. Rappresenta lo stato finale dell'implementazione di Reliable Web App per una società fittizia denominata Relecloud. Si tratta di un'app Web di livello di produzione che include tutti gli aggiornamenti di codice, architettura e configurazione descritti in questo articolo. Distribuire e usare l'implementazione di riferimento per guidare l'implementazione del modello di app Web Reliable.

Come implementare il modello di app Web Reliable

Questo articolo include le linee guida per l'architettura, il codice e la configurazione per implementare il modello Reliable Web App. Usare i collegamenti seguenti per passare alle indicazioni specifiche necessarie:

  • Contesto aziendale: allineare queste linee guida al contesto aziendale e imparare a definire obiettivi immediati e a lungo termine che determinano decisioni di riformatura.
  • Indicazioni sull'architettura: informazioni su come selezionare i servizi cloud corretti e progettare un'architettura che soddisfi i requisiti aziendali.
  • Linee guida sul codice: implementare tre modelli di progettazione per migliorare l'affidabilità e l'efficienza delle prestazioni dell'app Web nel cloud: ripetizione dei tentativi, interruttore e modelli cache-aside
  • Indicazioni sulla configurazione: configurare l'autenticazione e l'autorizzazione, le identità gestite, gli ambienti con diritti, l'infrastruttura come codice e il monitoraggio.

Contesto aziendale

Il primo passaggio per ripiattaformare un'app Web consiste nel definire gli obiettivi aziendali. È consigliabile definire obiettivi immediati, ad esempio obiettivi del livello di servizio e obiettivi di ottimizzazione dei costi, nonché obiettivi futuri per l'applicazione Web. Questi obiettivi influenzano la scelta dei servizi cloud e l'architettura dell'applicazione Web nel cloud. Definire uno SLO di destinazione per l'app Web, ad esempio il tempo di attività del 99,9%. Calcolare il contratto di servizio composito per tutti i servizi che influiscono sulla disponibilità dell'app Web.

Relecloud, ad esempio, ha una previsione di vendita positiva e prevede un aumento della domanda sull'app Web di creazione di ticket. Per soddisfare questa domanda, hanno definito gli obiettivi per l'applicazione Web:

  • Applicare modifiche al codice a basso costo e alto valore
  • Raggiungere un obiettivo del livello di servizio (SLO) del 99,9%
  • Adottare procedure DevOps
  • Creare ambienti ottimizzati per i costi
  • Migliorare l'affidabilità e la sicurezza

L'infrastruttura locale di Relecloud non era una soluzione conveniente per raggiungere questi obiettivi. Quindi, hanno deciso che la migrazione dell'applicazione Web ad Azure è stata il modo più conveniente per raggiungere gli obiettivi immediati e futuri.

Linee guida per l'architettura

Il modello Reliable Web App include alcuni elementi architetturali essenziali. È necessario dns per gestire la risoluzione degli endpoint, un web application firewall per bloccare il traffico HTTP dannoso e un servizio di bilanciamento del carico per proteggere e instradare le richieste degli utenti in ingresso. La piattaforma dell'applicazione ospita il codice dell'app Web e effettua chiamate a tutti i servizi back-end tramite endpoint privati in una rete virtuale. Uno strumento di monitoraggio delle prestazioni dell'applicazione acquisisce metriche e log per comprendere l'app Web.

Diagramma che mostra gli elementi architetturali essenziali del modello Reliable Web App.

Figura 1. Elementi architetturali essenziali del modello Reliable Web App.

Progettare l'architettura

Progettare l'infrastruttura per supportare le metriche di ripristino, ad esempio l'obiettivo del tempo di ripristino (RTO) e l'obiettivo del punto di ripristino (RPO). L'obiettivo RTO influisce sulla disponibilità e deve supportare lo SLO. Determinare un obiettivo del punto di ripristino (RPO) e configurare la ridondanza dei dati per soddisfare l'obiettivo rpo.

  • Scegliere l'affidabilità dell'infrastruttura. Determinare il numero di aree e zone di disponibilità necessarie per soddisfare le esigenze di disponibilità. Aggiungere zone di disponibilità e aree fino a quando il contratto di servizio composito non soddisfa lo SLO. Il modello Reliable Web App supporta più aree per una configurazione attiva-attiva o attiva-passiva. Ad esempio, l'implementazione di riferimento usa una configurazione attiva-passiva per soddisfare un SLO pari al 99,9%.

    Per un'app Web in più aree, configurare il servizio di bilanciamento del carico per instradare il traffico alla seconda area per supportare una configurazione attiva-attiva o passiva attiva a seconda delle esigenze aziendali. Le due aree richiedono gli stessi servizi ad eccezione di un'area con una rete virtuale hub che connette le aree. Adottare una topologia di rete hub-spoke per centralizzare e condividere risorse, ad esempio un firewall di rete. Se si dispone di macchine virtuali, aggiungere un bastion host alla rete virtuale hub per gestirli in modo sicuro (vedere la figura 2).

    Diagramma che mostra il modello Reliable Web App con una seconda area e una topologia hub-spoke.

    Figura 2. Modello Reliable Web App con una seconda area e una topologia hub-spoke.

  • Scegliere una topologia di rete. Scegliere la topologia di rete appropriata per i requisiti web e di rete. Se si prevede di avere più reti virtuali, usare una topologia di rete hub-spoke. Offre vantaggi in termini di costi, gestione e sicurezza con opzioni di connettività ibrida alle reti locali e virtuali.

Scegliere i servizi di Azure corretti

Quando si sposta un'app Web nel cloud, è necessario selezionare i servizi di Azure che soddisfano i requisiti aziendali e allinearsi alle funzionalità correnti dell'app Web locale. L'allineamento consente di ridurre al minimo lo sforzo di ripiattaforma. Ad esempio, usare i servizi che consentono di mantenere lo stesso motore di database e supportare il middleware e i framework esistenti. Le sezioni seguenti forniscono indicazioni per selezionare i servizi di Azure corretti per l'app Web.

Ad esempio, prima del passaggio al cloud, l'app Web di creazione di ticket di Relecloud era un'app locale monolitica ASP.NET. È stato eseguito in due macchine virtuali e aveva un database di Microsoft SQL Server. L'app Web ha subito problemi comuni di scalabilità e distribuzione delle funzionalità. Questo punto di partenza, i loro obiettivi aziendali e SLO hanno guidato le loro scelte di servizio.

  • Piattaforma dell'applicazione: usare app Azure Service come piattaforma dell'applicazione. Relecloud ha scelto app Azure Servizio come piattaforma dell'applicazione per i motivi seguenti:

    • Contratto di servizio elevato: ha un contratto di servizio elevato che soddisfa lo SLO dell'ambiente di produzione del 99,9%.
    • Riduzione del sovraccarico di gestione: si tratta di una soluzione completamente gestita che gestisce il ridimensionamento, i controlli di integrità e il bilanciamento del carico.
    • Supporto .NET: supporta la versione di .NET in cui è scritta l'applicazione.
    • Funzionalità di containerizzazione: l'app Web può convergere nel cloud senza contenitori, ma la piattaforma dell'applicazione supporta anche la containerizzazione senza modificare i servizi di Azure.
    • Scalabilità automatica: l'app Web può aumentare e ridurre automaticamente le prestazioni in base al traffico utente e alle impostazioni di configurazione. La piattaforma supporta anche l'aumento o la riduzione delle prestazioni per soddisfare requisiti di hosting diversi.
  • Gestione delle identità: usare Microsoft Entra ID come soluzione di gestione delle identità e degli accessi. Relecloud ha scelto Microsoft Entra ID per i motivi seguenti:

    • Autenticazione e autorizzazione: l'applicazione deve autenticare e autorizzare i dipendenti del call center.
    • Scalabile: è scalabile per supportare scenari di dimensioni maggiori.
    • Controllo dell'identità utente: i dipendenti del call center possono usare le identità aziendali esistenti.
    • Supporto del protocollo di autorizzazione: supporta OAuth 2.0 per le identità gestite.
  • Database: usare un servizio che consente di mantenere lo stesso motore di database. Usare l'albero delle decisioni dell'archivio dati. L'app Web di Relecloud usa SQL Server locale. Volevano quindi usare lo schema del database, le stored procedure e le funzioni esistenti. Diversi prodotti SQL sono disponibili in Azure, ma Relecloud ha scelto database SQL di Azure per i motivi seguenti:

    • Affidabilità: il livello per utilizzo generico offre un contratto di servizio elevato e ridondanza in più aree. Può supportare un carico utente elevato.
    • Riduzione del sovraccarico di gestione: fornisce un'istanza del database SQL gestita.
    • Supporto per la migrazione: supporta la migrazione del database da SQL Server locale.
    • Coerenza con le configurazioni locali: supporta le stored procedure, le funzioni e le viste esistenti.
    • Resilienza: supporta i backup e il ripristino temporizzato.
    • Esperienza e rielaborazione minima: database SQL sfrutta le competenze interne e richiede un lavoro minimo da adottare.
  • Monitoraggio delle prestazioni dell'applicazione: usare Application Insights per analizzare i dati di telemetria nell'applicazione. Relecloud ha scelto di usare Application Insights per i motivi seguenti:

    • Integrazione con Monitoraggio di Azure: offre la migliore integrazione con Monitoraggio di Azure.
    • Rilevamento anomalie: rileva automaticamente le anomalie delle prestazioni.
    • Risoluzione dei problemi: consente di diagnosticare i problemi nell'app in esecuzione.
    • Monitoraggio: raccoglie informazioni sul modo in cui gli utenti usano l'app e consente di tenere traccia facilmente degli eventi personalizzati.
    • Gap di visibilità: la soluzione locale non ha una soluzione di monitoraggio delle prestazioni dell'applicazione. Application Insights offre un'integrazione semplice con la piattaforma e il codice dell'applicazione.
  • Cache: scegliere se aggiungere cache all'architettura dell'app Web. cache di Azure per Redis è la soluzione di cache primaria di Azure. Si tratta di un archivio dati gestito in memoria basato sul software Redis. Il carico dell'app Web di Relecloud è fortemente asimmetrico rispetto alla visualizzazione dei concerti e dei dettagli delle sedi e ha aggiunto cache di Azure per Redis per i motivi seguenti:

    • Riduzione del sovraccarico di gestione: si tratta di un servizio completamente gestito.
    • Velocità e volume: ha velocità effettiva elevata dei dati e letture a bassa latenza per i dati a modifica lenta e di accesso comune.
    • Supporto diversificato: si tratta di un percorso unificato della cache per tutte le istanze dell'app Web da usare.
    • Archivio dati esterno: i server applicazioni locali hanno eseguito la memorizzazione nella cache locale della macchina virtuale. Questa configurazione non ha scaricato dati molto frequenti e non è stato possibile invalidare i dati.
    • Sessioni non di tiposticky: l'esternalizzazione dello stato della sessione supporta sessioni non di tipostick.
  • Bilanciamento del carico: le applicazioni Web che usano soluzioni PaaS devono usare Frontdoor di Azure, app Azure lication Gateway o entrambi in base all'architettura e ai requisiti dell'app Web. Usare l'albero delle decisioni del servizio di bilanciamento del carico per selezionare il bilanciamento del carico corretto. Relecloud necessita di un servizio di bilanciamento del carico di livello 7 che potrebbe instradare il traffico tra più aree. Relecloud aveva bisogno di un'app Web in più aree per soddisfare lo SLO del 99,9%. Relecloud ha scelto Frontdoor di Azure per i motivi seguenti:

    • Bilanciamento del carico globale: si tratta di un servizio di bilanciamento del carico di livello 7 in grado di instradare il traffico tra più aree.
    • Web application firewall: si integra in modo nativo con Web application firewall di Azure.
    • Flessibilità di routing: consente al team dell'applicazione di configurare l'ingresso deve supportare le modifiche future nell'applicazione.
    • Accelerazione del traffico: usa anycast per raggiungere il punto di presenza di Azure più vicino e trovare la route più veloce per l'app Web.
    • Domini personalizzati: supporta nomi di dominio personalizzati con convalida del dominio flessibile.
    • Probe di integrità: l'applicazione richiede il monitoraggio intelligente dei probe di integrità. Frontdoor di Azure usa le risposte del probe per determinare l'origine migliore per il routing delle richieste client.
    • Supporto per il monitoraggio: supporta i report predefiniti con un dashboard all-in-one per frontdoor e modelli di sicurezza. È possibile configurare avvisi che si integrano con Monitoraggio di Azure. Consente al registro applicazioni di ogni richiesta e probe di integrità non riusciti.
    • Protezione DDoS: include protezione DDoS di livello 3-4 incorporata.
    • Rete per la distribuzione di contenuti: posiziona Relecloud per usare una rete per la distribuzione di contenuti. La rete per la distribuzione di contenuti fornisce l'accelerazione del sito.
  • Web application firewall: usare Web application firewall di Azure per fornire protezione centralizzata da exploit Web e vulnerabilità comuni. Relecloud ha usato Web application firewall di Azure per i motivi seguenti:

    • Protezione globale: offre una migliore protezione globale delle app Web senza sacrificare le prestazioni.
    • Protezione botnet: il team può monitorare e configurare le impostazioni per risolvere i problemi di sicurezza correlati alle botnet.
    • Parità con l'ambiente locale: la soluzione locale era in esecuzione dietro un web application firewall gestito dall'IT.
    • Facilità d'uso: Web Application Firewall si integra con Frontdoor di Azure.
  • Archiviazione della configurazione: scegliere se aggiungere l'archiviazione di configurazione dell'app all'app Web. app Azure Configurazione è un servizio per la gestione centralizzata delle impostazioni dell'applicazione e dei flag di funzionalità. Esaminare Configurazione app procedure consigliate per decidere se questo servizio è adatto per l'app. Relecloud voleva sostituire la configurazione basata su file con un archivio di configurazione centrale che si integra con la piattaforma e il codice dell'applicazione. Sono stati aggiunti Configurazione app all'architettura per i motivi seguenti:

    • Flessibilità: supporta i flag di funzionalità. I flag di funzionalità consentono agli utenti di acconsentire esplicitamente alle funzionalità di anteprima anticipata in un ambiente di produzione senza ridistribuire l'app.
    • Supporta la pipeline Git: origine della verità per i dati di configurazione necessari per essere un repository Git. Pipeline necessaria per aggiornare i dati nell'archivio di configurazione centrale.
    • Supporta le identità gestite: supporta le identità gestite per semplificare e proteggere la connessione all'archivio di configurazione.
  • Gestione segreti: usare Azure Key Vault se si hanno segreti da gestire in Azure. È possibile incorporare Key Vault nelle app .NET usando l'oggetto ConfigurationBuilder. L'app Web locale di Relecloud archivia i segreti nei file di configurazione del codice, ma è una procedura di sicurezza migliore per archiviare i segreti in un percorso che supporta il controllo degli accessi in base al ruolo e i controlli di controllo. Sebbene le identità gestite siano la soluzione preferita per la connessione alle risorse di Azure, Relecloud aveva segreti dell'applicazione necessari per la gestione. Relecloud ha usato Key Vault per i motivi seguenti:

    • Crittografia: supporta la crittografia dei dati inattivi e in transito.
    • Supporto delle identità gestite: i servizi dell'applicazione possono usare le identità gestite per accedere all'archivio segreto.
    • Monitoraggio e registrazione: facilita l'accesso di controllo e genera avvisi quando cambiano i segreti archiviati.
    • Integrazione: offre l'integrazione nativa con l'archivio di configurazione di Azure (Configurazione app) e la piattaforma di hosting Web (servizio app).
  • Soluzione di archiviazione: esaminare le opzioni di archiviazione di Azure per scegliere la soluzione di archiviazione appropriata in base alle esigenze. L'app Web locale di Relecloud aveva l'archiviazione su disco montata in ogni server Web, ma il team voleva usare una soluzione di archiviazione dei dati esterna. Relecloud ha scelto Archiviazione BLOB di Azure per i motivi seguenti:

    • Accesso sicuro: l'app Web può eliminare gli endpoint per l'accesso all'archiviazione esposta alla rete Internet pubblica con accesso anonimo.
    • Crittografia: crittografa i dati inattivi e in transito.
    • Resilienza: supporta l'archiviazione con ridondanza della zona. L'archiviazione con ridondanza della zona replica i dati in modo sincrono tra tre zone di disponibilità di Azure nell'area primaria. Ogni zona di disponibilità si trova in una posizione fisica separata con alimentazione, raffreddamento e rete indipendenti. Questa configurazione deve rendere resilienti le immagini di creazione di ticket contro la perdita.
  • Sicurezza degli endpoint: usare collegamento privato di Azure per accedere alle soluzioni platform-as-a-service tramite un endpoint privato nella rete virtuale. Il traffico tra la rete virtuale e il servizio passa attraverso la rete backbone Microsoft. Relecloud ha scelto collegamento privato per i motivi seguenti:

    • Comunicazione di sicurezza avanzata: consente all'applicazione di accedere privatamente ai servizi nella piattaforma Azure e riduce il footprint di rete degli archivi dati per proteggersi dalla perdita di dati.
    • Sforzo minimo: gli endpoint privati supportano la piattaforma dell'app Web e la piattaforma di database usata dall'app Web. Entrambe le piattaforme rispecchiano le configurazioni locali esistenti per modifiche minime.
  • Sicurezza di rete: usare Firewall di Azure per controllare il traffico in ingresso e in uscita a livello di rete. Usare Azure Bastion per connettersi alle macchine virtuali in modo sicuro senza esporre porte RDP/SSH. Relecloud ha adottato una topologia di rete hub-spoke e voleva inserire i servizi di sicurezza di rete condivisi nell'hub. Firewall di Azure migliora la sicurezza controllando tutto il traffico in uscita dagli spoke per aumentare la sicurezza di rete. Relecloud ha richiesto Azure Bastion per le distribuzioni sicure da un jump host nella subnet DevOps.

Linee guida per il codice

Per spostare correttamente un'app Web nel cloud, è necessario aggiornare il codice dell'app Web con il modello retry, circuit-breaker e lo schema di progettazione Cache-Aside.

Diagramma che mostra il ruolo dei modelli di progettazione nell'architettura essenziale dell'app Web affidabile.

Figura 3. Ruolo dei modelli di progettazione.

Ogni modello di progettazione offre vantaggi di progettazione del carico di lavoro allineati a uno degli altri pilastri del framework ben progettato. Ecco una panoramica dei modelli da implementare:

  1. Modello di ripetizione dei tentativi: il modello di ripetizione dei tentativi gestisce gli errori temporanei ritentando le operazioni che potrebbero non riuscire in modo intermittente. Implementare questo modello in tutte le chiamate in uscita ad altri servizi di Azure.

  2. Modello di interruttore: il modello interruttore impedisce a un'applicazione di ripetere le operazioni che non sono temporanee. Implementare questo modello in tutte le chiamate in uscita ad altri servizi di Azure.

  3. Modello Cache-Aside: il modello Cache-Aside aggiunge e recupera da una cache più frequentemente di un archivio dati. Implementare questo modello per le richieste al database.

Schema progettuale Affidabilità (RE) Sicurezza (SE) Ottimizzazione costi (CO) Eccellenza operativa (OE) Efficienza delle prestazioni (PE) Supporto dei principi WAF
Modello di ripetizione dei tentativi RE:07
Modello a interruttore RE:03
RE:07
PE:07
PE:11
Modello Cache Aside RE:05
PE:08
PE:12

Implementare il modello di ripetizione dei tentativi

Aggiungere il modello Di ripetizione dei tentativi al codice dell'applicazione per risolvere le interruzioni temporanee del servizio. Queste interruzioni sono denominate errori temporanei. Gli errori temporanei si risolvono in genere entro pochi secondi. Il modello Di ripetizione dei tentativi consente di inviare di nuovo richieste non riuscite. Consente inoltre di configurare i ritardi delle richieste e il numero di tentativi prima che venga concesso l'errore.

  • Usare meccanismi di ripetizione dei tentativi predefiniti Usare il meccanismo di ripetizione dei tentativi predefinito che la maggior parte dei servizi di Azure deve accelerare l'implementazione. Ad esempio, l'implementazione di riferimento usa la resilienza della connessione in Entity Framework Core per applicare il modello Di ripetizione dei tentativi nelle richieste a database SQL di Azure (vedere il codice seguente).

    services.AddDbContextPool<ConcertDataContext>(options => options.UseSqlServer(sqlDatabaseConnectionString,
        sqlServerOptionsAction: sqlOptions =>
        {
            sqlOptions.EnableRetryOnFailure(
            maxRetryCount: 5,
            maxRetryDelay: TimeSpan.FromSeconds(3),
            errorNumbersToAdd: null);
        }));
    
  • Usare librerie di programmazione di ripetizione dei tentativi. Per le comunicazioni HTTP, integrare una libreria di resilienza standard, ad esempio Polly o Microsoft.Extensions.Http.Resilience. Queste librerie offrono meccanismi completi di ripetizione dei tentativi fondamentali per la gestione delle comunicazioni con servizi Web esterni. Ad esempio, l'implementazione di riferimento usa Polly per applicare il modello Di ripetizione dei tentativi ogni volta che il codice costruisce un oggetto che chiama l'oggetto IConcertSearchService (vedere il codice seguente).

    private void AddConcertSearchService(IServiceCollection services)
    {
        var baseUri = Configuration["App:RelecloudApi:BaseUri"];
        if (string.IsNullOrWhiteSpace(baseUri))
        {
            services.AddScoped<IConcertSearchService, MockConcertSearchService>();
        }
        else
        {
            services.AddHttpClient<IConcertSearchService, RelecloudApiConcertSearchService>(httpClient =>
            {
                httpClient.BaseAddress = new Uri(baseUri);
                httpClient.DefaultRequestHeaders.Add(HeaderNames.Accept, "application/json");
                httpClient.DefaultRequestHeaders.Add(HeaderNames.UserAgent, "Relecloud.Web");
            })
            .AddPolicyHandler(GetRetryPolicy())
            .AddPolicyHandler(GetCircuitBreakerPolicy());
        }
    }
    
    private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
    {
        var delay = Backoff.DecorrelatedJitterBackoffV2(TimeSpan.FromMilliseconds(500), retryCount: 3);
        return HttpPolicyExtensions
          .HandleTransientHttpError()
          .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
          .WaitAndRetryAsync(delay);
    }
    

Implementazione dello schema Circuit Breaker

Usare il modello interruttore per gestire le interruzioni del servizio che non sono errori temporanei. Il modello interruttore impedisce a un'applicazione di tentare continuamente di accedere a un servizio non rispondente. Rilascia l'applicazione ed evita di sprecare cicli di CPU in modo che l'applicazione mantenga l'integrità delle prestazioni per gli utenti finali.

Ad esempio, l'implementazione di riferimento applica il modello a interruttore in tutte le richieste all'API. Usa la HandleTransientHttpError logica per rilevare le richieste HTTP che possono riprovare in modo sicuro, ma limita il numero di errori di aggregazione in un periodo di tempo specificato (vedere il codice seguente).

private static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
        .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
}

Implementare il modello Cache-Aside

Aggiungere il modello Cache-Aside all'app Web per migliorare la gestione dei dati in memoria. Il modello assegna all'applicazione la responsabilità di gestire le richieste di dati e garantire la coerenza tra la cache e un archivio permanente, ad esempio un database. Riduce i tempi di risposta, migliora la velocità effettiva e riduce la necessità di aumentare la scalabilità. Riduce anche il carico nell'archivio dati primario, migliorando l'affidabilità e l'ottimizzazione dei costi. Per implementare il modello Cache-Aside, seguire queste indicazioni:

  • Configurare l'applicazione per l'uso di una cache. Le app di produzione devono usare la cache Redis distribuita perché migliora le prestazioni riducendo le query di database e abilita sessioni non di tiposticky in modo che il servizio di bilanciamento del carico possa distribuire uniformemente il traffico. Ad esempio, l'implementazione di riferimento usa la cache Redis distribuita. Il AddAzureCacheForRedis metodo configura l'applicazione per l'uso di cache di Azure per Redis (vedere il codice seguente).

    private void AddAzureCacheForRedis(IServiceCollection services)
    {
        if (!string.IsNullOrWhiteSpace(Configuration["App:RedisCache:ConnectionString"]))
        {
            services.AddStackExchangeRedisCache(options =>
            {
                options.Configuration = Configuration["App:RedisCache:ConnectionString"];
            });
        }
        else
        {
            services.AddDistributedMemoryCache();
        }
    }
    
  • Memorizzare nella cache i dati con esigenze elevate. Applicare il modello Cache-Aside ai dati di necessità elevata per amplificarne l'efficacia. Usare Monitoraggio di Azure per tenere traccia della CPU, della memoria e dell'archiviazione del database. Queste metriche consentono di determinare se è possibile usare uno SKU di database più piccolo dopo aver applicato il modello Cache-Aside. Ad esempio, l'implementazione di riferimento memorizza nella cache i dati di elevata necessità che supportano la pagina Prossimi concerti. Il GetUpcomingConcertsAsync metodo esegue il pull dei dati nella cache Redis dalla database SQL e popola la cache con i dati dei concerti più recenti (vedere il codice seguente).

    public async Task<ICollection<Concert>> GetUpcomingConcertsAsync(int count)
    {
        IList<Concert>? concerts;
        var concertsJson = await this.cache.GetStringAsync(CacheKeys.UpcomingConcerts);
        if (concertsJson != null)
        {
            // There is cached data. Deserialize the JSON data.
            concerts = JsonSerializer.Deserialize<IList<Concert>>(concertsJson);
        }
        else
        {
            // There's nothing in the cache. Retrieve data 
            // from the repository and cache it for one hour.
            concerts = await this.database.Concerts.AsNoTracking()
                .Where(c => c.StartTime > DateTimeOffset.UtcNow && c.IsVisible)
                .OrderBy(c => c.StartTime)
                .Take(count)
                .ToListAsync();
            concertsJson = JsonSerializer.Serialize(concerts);
            var cacheOptions = new DistributedCacheEntryOptions {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1)
            };
            await this.cache.SetStringAsync(CacheKeys.UpcomingConcerts, concertsJson, cacheOptions);
        }
        return concerts ?? new List<Concert>();
    }
    
  • Mantenere aggiornati i dati della cache. Pianificare gli aggiornamenti regolari della cache per la sincronizzazione con le modifiche più recenti del database. Determinare la frequenza di aggiornamento ottimale in base alla volatilità dei dati e alle esigenze degli utenti. Questa procedura garantisce che l'applicazione usi il modello Cache-Aside per fornire sia l'accesso rapido che le informazioni correnti. Ad esempio, l'implementazione di riferimento memorizza nella cache i dati solo per un'ora e usa il CreateConcertAsync metodo per cancellare la chiave della cache quando i dati vengono modificati (vedere il codice seguente).

    public async Task<CreateResult> CreateConcertAsync(Concert newConcert)
    {
        database.Add(newConcert);
        await this.database.SaveChangesAsync();
        this.cache.Remove(CacheKeys.UpcomingConcerts);
        return CreateResult.SuccessResult(newConcert.Id);
    }
    
  • Garantire la coerenza dei dati. Implementare meccanismi per aggiornare la cache immediatamente dopo qualsiasi operazione di scrittura del database. Usare aggiornamenti basati su eventi o classi di gestione dei dati dedicate per garantire la coerenza della cache. La sincronizzazione coerente della cache con le modifiche del database è fondamentale per il modello Cache-Aside. Ad esempio, l'implementazione di riferimento usa il UpdateConcertAsync metodo per mantenere coerenti i dati nella cache (vedere il codice seguente).

    public async Task<UpdateResult> UpdateConcertAsync(Concert existingConcert), 
    {
       database.Update(existingConcert);
       await database.SaveChangesAsync();
       this.cache.Remove(CacheKeys.UpcomingConcerts);
       return UpdateResult.SuccessResult();
    }
    

Linee guida per la configurazione

Le sezioni seguenti forniscono indicazioni sull'implementazione degli aggiornamenti delle configurazioni. Ogni sezione è allineata a uno o più pilastri del framework ben progettato.

Impostazione Affidabilità (RE) Sicurezza (SE) Ottimizzazione costi (CO) Eccellenza operativa (OE) Efficienza delle prestazioni (PE) Supporto dei principi WAF
Configurare l'autenticazione utente e l'autorizzazione SE:05
OE:10
Implementare le identità gestite SE:05
OE:10
Ambienti di dimensioni corrette CO:05
CO:06
Implementare la scalabilità automatica RE:06
CO:12
PE:05
Automatizzare la distribuzione delle risorse OE:05
Implementare il monitoraggio OE:07
PE:04

Configurare l'autenticazione e l'autorizzazione degli utenti

Quando si esegue la migrazione di applicazioni Web ad Azure, configurare i meccanismi di autenticazione e autorizzazione degli utenti. Seguire questi elementi consigliati:

  • Usare una piattaforma di gestione delle identità. Usare Microsoft Identity Platform per configurare l'autenticazione dell'app Web. Questa piattaforma supporta applicazioni che usano una singola directory di Microsoft Entra, più directory di Microsoft Entra di organizzazioni diverse e identità Microsoft o account di social networking.

  • Crea una registrazione dell'app. Microsoft Entra ID richiede una registrazione dell'applicazione nel tenant primario. La registrazione dell'applicazione garantisce che gli utenti che ottengono l'accesso all'app Web abbiano identità nel tenant primario.

  • Usare le funzionalità della piattaforma. Ridurre al minimo la necessità di codice di autenticazione personalizzato usando le funzionalità della piattaforma per autenticare gli utenti e accedere ai dati. Ad esempio, servizio app fornisce supporto per l'autenticazione predefinita, in modo da poter accedere agli utenti e accedere ai dati scrivendo codice minimo o nessun codice nell'app Web.

  • Applicare l'autorizzazione nell'applicazione. Usare i controlli degli accessi in base al ruolo per assegnare privilegi minimi ai ruoli dell'applicazione. Definire ruoli specifici per azioni utente diverse per evitare sovrapposizioni e garantire chiarezza. Eseguire il mapping degli utenti ai ruoli appropriati e assicurarsi di avere accesso solo alle risorse e alle azioni necessarie.

  • Preferisce l'accesso temporaneo all'archiviazione. Usare le autorizzazioni temporanee per proteggersi da accessi non autorizzati e violazioni, ad esempio firme di accesso condiviso (SASs). Usare sas di delega utente per ottimizzare la sicurezza quando si concede l'accesso temporaneo. Si tratta dell'unica firma di accesso condiviso che usa le credenziali di Microsoft Entra ID e non richiede una chiave dell'account di archiviazione permanente.

  • Applicare l'autorizzazione in Azure. Usare il controllo degli accessi in base al ruolo di Azure per assegnare privilegi minimi alle identità utente. Il controllo degli accessi in base al ruolo di Azure determina quali identità delle risorse di Azure possono accedere, cosa possono fare con queste risorse e quali aree hanno accesso.

  • Evitare autorizzazioni con privilegi elevati permanenti. Usare Microsoft Entra Privileged Identity Management per concedere l'accesso JIT per le operazioni con privilegi. Ad esempio, gli sviluppatori spesso necessitano dell'accesso a livello di amministratore per creare/eliminare database, modificare gli schemi di tabella e modificare le autorizzazioni utente. Con l'accesso JIT, le identità utente ricevono autorizzazioni temporanee per eseguire attività con privilegi.

Implementare le identità gestite

Usare identità gestite per tutti i servizi di Azure che supportano le identità gestite. Un'identità gestita consente alle risorse di Azure (identità del carico di lavoro) di eseguire l'autenticazione e interagire con altri servizi di Azure senza gestire le credenziali. I sistemi ibridi e legacy possono mantenere le soluzioni di autenticazione locali per semplificare la migrazione, ma devono passare alle identità gestite il prima possibile. Per implementare le identità gestite, seguire queste indicazioni:

  • Selezionare il tipo corretto di identità gestita. Preferisce le identità gestite assegnate dall'utente quando si hanno due o più risorse di Azure che necessitano dello stesso set di autorizzazioni. Questa configurazione è più efficiente rispetto alla creazione di identità gestite assegnate dal sistema per ognuna di queste risorse e l'assegnazione delle stesse autorizzazioni a tutte. In caso contrario, usare le identità gestite assegnate dal sistema.

  • Configurare i privilegi minimi. Usare il controllo degli accessi in base al ruolo di Azure per concedere solo le autorizzazioni critiche per le operazioni, ad esempio le azioni CRUD nei database o l'accesso ai segreti. Le autorizzazioni di identità del carico di lavoro sono persistenti, quindi non è possibile fornire autorizzazioni JUST-In-Time o a breve termine per le identità del carico di lavoro. Se il controllo degli accessi in base al ruolo di Azure non copre uno scenario specifico, integrare il controllo degli accessi in base al ruolo di Azure con i criteri di accesso a livello di servizio di Azure.

  • Proteggere i segreti rimanenti. Archiviare eventuali segreti rimanenti in Azure Key Vault. Caricare i segreti da Key Vault all'avvio dell'applicazione anziché durante ogni richiesta HTTP. L'accesso ad alta frequenza all'interno delle richieste HTTP può superare i limiti delle transazioni di Key Vault. Archiviare le configurazioni dell'applicazione nella configurazione di app Azure.

Ad esempio, l'implementazione di riferimento usa l'argomento Authentication nel database SQL stringa di connessione in modo che servizio app possa connettersi al database SQL con un'identità gestita: Server=tcp:my-sql-server.database.windows.net,1433;Initial Catalog=my-sql-database;Authentication=Active Directory Default. Usa per DefaultAzureCredential consentire all'API Web di connettersi a Key Vault usando un'identità gestita (vedere il codice seguente).

    builder.Configuration.AddAzureAppConfiguration(options =>
    {
         options
            .Connect(new Uri(builder.Configuration["Api:AppConfig:Uri"]), new DefaultAzureCredential())
            .ConfigureKeyVault(kv =>
            {
                // Some of the values coming from Azure App Configuration
                // are stored in Key Vault. Use the managed identity
                // of this host for the authentication.
                kv.SetCredential(new DefaultAzureCredential());
            });
    });

Ambienti di dimensioni corrette

Usare i livelli di prestazioni (SKU) dei servizi di Azure che soddisfano le esigenze di ogni ambiente senza eccesso. Per adattare le dimensioni degli ambienti, seguire queste indicazioni:

  • Stimare i costi. Usare il calcolatore prezzi di Azure per stimare il costo di ogni ambiente.

  • Ottimizzare i costi per gli ambienti di produzione. Gli ambienti di produzione necessitano di SKU che soddisfino i contratti di servizio (SLA), le funzionalità e la scalabilità necessarie per la produzione. Monitorare continuamente l'utilizzo delle risorse e regolare gli SKU per allinearsi alle esigenze di prestazioni effettive.

  • Ottimizzare i costi per gli ambienti di preproduzione. Gli ambienti di preproduzione devono usare risorse a basso costo, disabilitare i servizi non necessarie e applicare sconti come i prezzi di sviluppo/test di Azure. Assicurarsi che gli ambienti di preproduzione siano sufficientemente simili alla produzione per evitare di introdurre rischi. Questo equilibrio garantisce che i test rimangano efficaci senza incorrere in costi non necessari.

  • Definire GLI SKU usando l'infrastruttura come codice (IaC). Implementare IaC per selezionare e distribuire dinamicamente gli SKU corretti in base all'ambiente. Questo approccio migliora la coerenza e semplifica la gestione.

Ad esempio, l'implementazione di riferimento usa i parametri Bicep per distribuire livelli (SKU) più costosi nell'ambiente di produzione.

    var redisCacheSkuName = isProd ? 'Standard' : 'Basic'
    var redisCacheFamilyName = isProd ? 'C' : 'C'
    var redisCacheCapacity = isProd ? 1 : 0

Implementare la scalabilità automatica

La scalabilità automatica garantisce che un'app Web rimanga resiliente, reattiva e in grado di gestire in modo efficiente i carichi di lavoro dinamici. Per implementare la scalabilità automatica, seguire queste indicazioni:

  • Automatizzare la scalabilità orizzontale. Usare la scalabilità automatica di Azure per automatizzare la scalabilità orizzontale negli ambienti di produzione. Configurare le regole di scalabilità automatica per aumentare il numero di istanze in base alle metriche delle prestazioni chiave, in modo che l'applicazione possa gestire carichi variabili.

  • Perfezionare i trigger di ridimensionamento. Iniziare con l'utilizzo della CPU come trigger di ridimensionamento iniziale se non si ha familiarità con i requisiti di ridimensionamento dell'applicazione. Perfezionare i trigger di ridimensionamento per includere altre metriche, ad esempio RAM, velocità effettiva di rete e I/O del disco. L'obiettivo è corrispondere al comportamento dell'applicazione Web per ottenere prestazioni migliori.

  • Fornire un buffer di scalabilità orizzontale. Impostare le soglie di ridimensionamento da attivare prima di raggiungere la capacità massima. Ad esempio, configurare il ridimensionamento in modo che si verifichi con un utilizzo della CPU dell'85% anziché attendere fino a raggiungere il 100%. Questo approccio proattivo consente di mantenere le prestazioni ed evitare potenziali colli di bottiglia.

Automatizzare la distribuzione delle risorse

Usare l'automazione per distribuire e aggiornare le risorse e il codice di Azure in tutti gli ambienti. Seguire questi elementi consigliati:

  • Usare l'infrastruttura come codice. Distribuire l'infrastruttura come codice tramite pipeline di integrazione continua e recapito continuo (CI/CD). Azure include modelli Bicep, ARM (JSON) e Terraform predefiniti per ogni risorsa di Azure.

  • Usare una pipeline di integrazione continua/distribuzione continua (CI/CD). Usare una pipeline CI/CD per distribuire il codice dal controllo del codice sorgente ai vari ambienti, ad esempio test, gestione temporanea e produzione. Usare Azure Pipelines se si usa Azure DevOps o GitHub Actions per i progetti GitHub.

  • Integrare unit test. Classificare in ordine di priorità l'esecuzione e il passaggio di tutti gli unit test all'interno della pipeline prima di qualsiasi distribuzione alle servizio app. Incorporare strumenti di qualità del codice e copertura come SonarQube per ottenere una copertura completa dei test.

  • Adottare un framework fittizio. Per i test che coinvolgono endpoint esterni, usare framework fittizi. Questi framework consentono di creare endpoint simulati. Eliminano la necessità di configurare endpoint esterni reali e garantire condizioni di test uniformi in ambienti diversi.

  • Eseguire analisi di sicurezza. Usare test di sicurezza delle applicazioni statici (SAST) per individuare i difetti di sicurezza e gli errori di codifica nel codice sorgente. Inoltre, eseguire l'analisi della composizione software (SCA) per esaminare librerie e componenti di terze parti per individuare i rischi per la sicurezza. Gli strumenti per queste analisi sono facilmente integrati sia in GitHub che in Azure DevOps.

Implementare il monitoraggio

Implementare il monitoraggio delle applicazioni e della piattaforma per migliorare l'eccellenza operativa e l'efficienza delle prestazioni dell'app Web. Per implementare il monitoraggio, seguire queste raccomandazioni:

  • Raccogliere i dati di telemetria dell'applicazione. Usare l'strumentazione automatica in app Azure lication Insights per raccogliere dati di telemetria dell'applicazione, ad esempio velocità effettiva delle richieste, durata media delle richieste, errori e monitoraggio delle dipendenze, senza modifiche al codice.

    L'implementazione di riferimento usa AddApplicationInsightsTelemetry dal pacchetto Microsoft.ApplicationInsights.AspNetCore NuGet per abilitare la raccolta di dati di telemetria (vedere il codice seguente).

    public void ConfigureServices(IServiceCollection services)
    {
       ...
       services.AddApplicationInsightsTelemetry(Configuration["App:Api:ApplicationInsights:ConnectionString"]);
       ...
    }
    
  • Creare metriche dell'applicazione personalizzate. Usare la strumentazione basata su codice per i dati di telemetria dell'applicazione personalizzati. Aggiungere Application Insights SDK al codice e usare l'API di Application Insights.

    L'implementazione di riferimento raccoglie i dati di telemetria sugli eventi correlati all'attività del carrello. this.telemetryClient.TrackEvent conta i biglietti aggiunti al carrello. Fornisce il nome dell'evento (AddToCart) e specifica un dizionario con concertId e count (vedere il codice seguente).

    this.telemetryClient.TrackEvent("AddToCart", new Dictionary<string, string> {
        { "ConcertId", concertId.ToString() },
        { "Count", count.ToString() }
    });
    
  • Monitorare la piattaforma. Abilitare la diagnostica per tutti i servizi supportati e inviare la diagnostica alla stessa destinazione dei log applicazioni per la correlazione. I servizi di Azure creano automaticamente i log della piattaforma, ma li archivia solo quando si abilita la diagnostica. Abilitare le impostazioni di diagnostica per ogni servizio che supporta la diagnostica.

Distribuire l'implementazione di riferimento

L'implementazione di riferimento guida gli sviluppatori attraverso una migrazione simulata da un'applicazione ASP.NET locale ad Azure, evidenziando le modifiche necessarie durante la fase di adozione iniziale. Questo esempio usa un'applicazione di ticket per concerti per la società fittizia Relecloud, che vende biglietti tramite l'applicazione Web locale. Relecloud ha impostato gli obiettivi seguenti per l'applicazione Web:

  • Implementare modifiche al codice a basso costo e alto valore
  • Raggiungere un obiettivo del livello di servizio (SLO) del 99,9%
  • Adottare procedure DevOps
  • Creare ambienti ottimizzati per i costi
  • Migliorare l'affidabilità e la sicurezza

Relecloud ha determinato che l'infrastruttura locale non era una soluzione conveniente per soddisfare questi obiettivi. Hanno deciso che la migrazione dell'applicazione Web CAMS ad Azure è stata il modo più conveniente per raggiungere gli obiettivi immediati e futuri. L'architettura seguente rappresenta lo stato finale dell'implementazione del modello Reliable Web App di Relecloud.

Diagramma che mostra l'architettura dell'implementazione di riferimento.Figura 3. Architettura dell'implementazione di riferimento. Scaricare un file di Visio di questa architettura.