Editar

Compartir a través de


Patrón Reliable Web App para .NET

Azure App Service
Azure Front Door
Azure Cache for Redis
.NET

Este artículo proporciona orientación sobre la implementación del patrón Reliable Web App. Este patrón describe cómo modificar (replanificar) aplicaciones web para la migración a la nube. Ofrece orientación prescriptiva sobre arquitectura, código y configuración en consonancia con los principios del Marco de trabajo bien diseñado.

¿Por qué el patrón Reliable Web App para .NET?

El patrón Reliable Web App es un conjunto de principios y técnicas de implementación que definen el modo en que se deben replanificar las aplicaciones web al migrar a la nube. Se centra en las actualizaciones mínimas de código que hay que hacer para tener éxito en la nube. La siguiente guía utiliza la implementación de referencia como ejemplo y sigue el viaje de replataforma de la empresa ficticia, Relecloud, para proporcionar contexto empresarial para su viaje. Antes de implantar el patrón Reliable Web App para .NET, Relecloud tenía una aplicación web de venta de entradas monolítica y local que utilizaba el marco ASP.NET.

Sugerencia

Logotipo de GitHub Existe una implementación de referencia (ejemplo) del patrón Reliable Web App. Representa el estado final de la implementación de Reliable Web App para una empresa ficticia llamada Relecloud. Se trata de una aplicación web de producción que incluye todas las actualizaciones de código, arquitectura y configuración comentadas en este artículo. Implemente y utilice la implementación de referencia para guiar su implementación del patrón Reliable Web App.

Cómo implementar el patrón Reliable Web App

Este artículo incluye orientación sobre arquitectura, código y configuración para implantar el patrón Reliable Web App. Utilice los siguientes enlaces para navegar hasta la orientación específica que necesita:

  • Contexto empresarial: Alinee esta orientación con su contexto empresarial y aprenda a definir objetivos inmediatos y a largo plazo que impulsen las decisiones de replanificación.
  • Orientación sobre arquitectura: Aprenda a seleccionar los servicios en la nube adecuados y a diseñar una arquitectura que satisfaga sus requisitos empresariales.
  • Guía de código: Implemente tres patrones de diseño para mejorar la fiabilidad y la eficiencia del rendimiento de su aplicación web en la nube: Los patrones Retry, Circuit-Breaker y Cache-Aside.
  • Guía de configuración: Configure la autenticación y la autorización, las identidades administradas, los entornos con derechos, la infraestructura como código y la supervisión.

Contexto empresarial

El primer paso para replanificar una aplicación web es definir sus objetivos empresariales. Debe establecer objetivos inmediatos, como objetivos de nivel de servicio y objetivos de optimización de costes, así como objetivos futuros para su aplicación web. Estos objetivos influyen en la elección de servicios en la nube y en la arquitectura de la aplicación web en la nube. Defina un objetivo de SLO para su aplicación web, como un tiempo de actividad del 99,9 %. Calcule el SLA compuesto para todos los servicios que afectan a la disponibilidad de su aplicación web.

Por ejemplo, Relecloud tiene una previsión de ventas positiva y prevé un aumento de la demanda en su aplicación web de venta de entradas. Para satisfacer esta demanda, definieron los objetivos de la aplicación web:

  • Aplicar cambios de bajo costo y alto valor
  • Alcanzar un objetivo de nivel de servicio (SLO) del 99,9 %
  • Adoptar las prácticas de DevOps
  • Crear entornos con costes optimizados
  • Mejorar la confiabilidad y la seguridad

La infraestructura local de Relecloud no era una solución rentable para alcanzar estos objetivos. Así que decidieron que migrar su aplicación web a Azure era la manera más rentable de alcanzar sus objetivos inmediatos y futuros.

Guía de arquitectura

El Reliable Web App fiable tiene algunos elementos arquitectónicos esenciales. Necesita DNS para administrar la resolución de puntos de conexión, un firewall de aplicaciones web para bloquear el tráfico HTTP malicioso y un equilibrador de carga para proteger y enrutar las solicitudes entrantes de los usuarios. La plataforma de aplicaciones aloja el código de su aplicación web y realiza llamadas a todos los servicios backend a través de puntos de conexión privados en una red virtual. Una herramienta de supervisión del rendimiento de la aplicación captura métricas y registros para comprender su aplicación web.

Diagrama que muestra los elementos arquitectónicos esenciales del patrón Reliable Web App.

Figura 1. Elementos arquitectónicos esenciales del patrón Reliable Web App.

Diseño de la arquitectura

Diseñe su infraestructura para soportar sus métricas de recuperación, como el objetivo de tiempo de recuperación (RTO) y el objetivo de punto de recuperación (RPO). El RTO afecta a la disponibilidad y debe ser compatible con su SLO. Determine un objetivo de punto de recuperación (RPO) y configure la redundancia de datos para cumplir el RPO.

  • Elija la fiabilidad de la infraestructura. Determine cuántas zonas y regiones de disponibilidad necesita para satisfacer sus necesidades de disponibilidad. Añada zonas y regiones de disponibilidad hasta que el SLA compuesto cumpla su SLO. El patrón Reliable Web App admite varias regiones para una configuración activo-activo o activo-pasivo. Por ejemplo, la implementación de referencia utiliza una configuración activa-pasiva para cumplir un SLO del 99,9 %.

    Para una aplicación web multirregión, configure su equilibrador de carga para enrutar el tráfico a la segunda región con el fin de admitir una configuración activa-activa o activa-pasiva en función de sus necesidades empresariales. Las dos regiones requieren los mismos servicios, excepto que una de las regiones tiene una red virtual concentradora que conecta las regiones. Adopte una topología de red radial para centralizar y compartir recursos, como un firewall de red. Si tiene máquinas virtuales, añada un host bastión a la red virtual hub para administrarlas de forma segura (consulte la figura 2).

    Diagrama que muestra el patrón de Reliable Web App con una segunda región y una topología radial.

    Ilustración 2. El patrón de Reliable Web App con una segunda región y una topología radial.

  • Elija una topología de red. Elija la topología de red adecuada para los requisitos web y de red. Si tiene previsto disponer de varias redes virtuales, utilice una topología de red radial. Proporciona ventajas de coste, administración y seguridad con opciones de conectividad híbrida a redes locales y virtuales.

Elija los servicios Azure adecuados

Al trasladar una aplicación web a la nube, debe seleccionar los servicios de Azure que satisfagan sus requisitos empresariales y se ajusten a las funciones actuales de la aplicación web local. La alineación ayuda a minimizar el esfuerzo de cambio de plataforma. Por ejemplo, utilice servicios que le permitan mantener el mismo motor de base de datos y sean compatibles con el middleware y los marcos existentes. Las siguientes secciones proporcionan orientación para seleccionar los servicios Azure adecuados para su aplicación web.

Por ejemplo, antes de trasladarse a la nube, la aplicación web de venta de entradas de Relecloud era una aplicación ASP.NET local y monolítica. Se ejecutaba en dos máquinas virtuales y tenía una base de datos Microsoft SQL Server. La aplicación web sufría los problemas habituales de escalabilidad e implementación de características. Este punto de partida, sus objetivos empresariales y el SLO impulsaron su elección de servicios.

  • Plataforma de aplicaciones: Utilice Azure App Service como plataforma de aplicaciones. Relecloud eligió Azure App Service como plataforma de aplicaciones por los siguientes motivos:

    • Contrato de nivel de servicio (SLA) elevado: Tiene un SLA elevado que cumple el SLO del entorno de producción del 99,9 %.
    • Reducción de los gastos generales de gestión: Es una solución totalmente administrada que controla el escalado, las comprobaciones de estado y el equilibrio de carga.
    • Compatibilidad con .NET: Admite la versión de .NET en la que se escribe la aplicación..
    • Capacidad de contenedorización: La aplicación web puede converger en la nube sin contenedorizar, pero la plataforma de aplicaciones también admite la contenedorización sin cambiar los servicios de Azure.
    • Escalabilidad automática: La aplicación web puede escalarse automáticamente en función del tráfico de usuarios y los ajustes de configuración. La plataforma también admite la ampliación o reducción para adaptarse a diferentes requisitos de hosting.
  • administración de identidades: Utilice Microsoft Entra ID como solución de administración de identidades y accesos. Relecloud eligió Microsoft Entra ID por los siguientes motivos:

    • Autenticación y autorización: La aplicación debe autenticar y autorizar a los empleados del centro de llamadas.
    • Escalable: Se escala para admitir escenarios más grandes.
    • Control de identidad de usuario: Los empleados del centro de llamadas pueden usar sus identidades empresariales existentes.
    • Compatibilidad con el protocolo de autorización: Admite OAuth 2.0 para identidades administradas.
  • Base de datos: Utilice un servicio que le permita mantener el mismo motor de base de datos. Utilice el árbol de decisión de almacén de datos. La aplicación web de Relecloud utilizaba SQL Server en sus instalaciones. Por tanto, querían utilizar el esquema de base de datos, los procedimientos almacenados y las funciones existentes. Hay varios productos SQL disponibles en Azure, pero Relecloud eligió Azure SQL Database por los siguientes motivos:

    • Confiabilidad: El nivel de uso general proporciona un acuerdo de nivel de servicio elevado y redundancia multirregión. Puede admitir una carga de usuario elevada.
    • Reducción de los gastos generales de gestión: Proporciona una instancia administrada de SQL Database.
    • Compatibilidad con la migración: Admite la migración de bases de datos desde SQL Server local.
    • Coherencia con configuraciones locales: Admite los procedimientos almacenados, funciones y vistas existentes.
    • Resistencia: Copias de seguridad automatizadas y restauración a un momento dado.
    • Experiencia y retrabajo mínimo: La base de datos SQL aprovecha la experiencia interna y su adopción requiere un trabajo mínimo.
  • Supervisión del rendimiento de las aplicaciones: Utilice Application Insights para analizar la telemetría de su aplicación. Relecloud decidió utilizar Application Insights por las siguientes razones:

    • Integración con Azure Monitor: Proporciona la mejor integración con Azure Monitor.
    • Detección de anomalías: Detecta automáticamente las anomalías de rendimiento.
    • Solución de problemas: Ayuda a diagnosticar problemas de la aplicación en ejecución.
    • Supervisión: Recopila información sobre cómo los usuarios usan la aplicación y permite realizar un seguimiento sencillo de los eventos personalizados.
    • Brecha de visibilidad: La solución local no contaba con una solución de supervisión del rendimiento de las aplicaciones. Application Insights proporciona una integración sencilla con la plataforma y el código de la aplicación.
  • Caché: Elija si desea añadir caché a la arquitectura de su aplicación web. Azure Cache for Redis es la solución de caché principal de Azure. Es un almacén de datos en memoria administrado basado en el software Redis. La carga de la aplicación web de Relecloud está muy sesgada hacia la visualización de conciertos y detalles del lugar, y añadió Azure Cache for Redis por los siguientes motivos:

    • Reducción de los gastos generales de gestión: Es un servicio totalmente administrado.
    • Velocidad y volumen: Tiene un rendimiento de datos alto y lecturas de baja latencia para los datos a los que se accede con frecuencia y que cambian poco.
    • Amplia compatibilidad: Se trata de una ubicación de caché unificada para que todas las instancias de la aplicación web la usen.
    • Almacén de datos externos: Los servidores de aplicaciones locales realizaron el almacenamiento en caché local de la máquina virtual. Esta configuración no ha descargado datos muy frecuentes y no ha podido invalidar los datos.
    • Sesiones no permanentes: La externalización del estado de la sesión admite sesiones no permanentes.
  • Equilibrador de carga: Las aplicaciones web que utilizan soluciones PaaS deben utilizar Azure Front Door, Azure Application Gateway o ambos en función de la arquitectura y los requisitos de la aplicación web. Utilice el árbol de decisión del equilibrador de carga para elegir el equilibrador de carga adecuado. Relecloud necesitaba un equilibrador de carga de capa 7 que pudiera enrutar el tráfico a través de varias regiones. Relecloud necesitaba una aplicación web de varias regiones para cumplir el SLO del 99,9 %. Relecloud eligió Azure Front Door por los siguientes motivos:

    • Equilibrio de carga global: Es un equilibrador de carga de capa 7 que puede enrutar el tráfico a través de varias regiones.
    • Firewall de aplicaciones web: Se integra de forma nativa con Azure Web Application Firewall.
    • Flexibilidad de enrutamiento: Permite que el equipo de la aplicación configure las necesidades de entrada para admitir los cambios futuros en la aplicación.
    • Aceleración de tráfico: Usa cualquier difusión para llegar al punto de presencia de Azure más cercano y encontrar la ruta más rápida a la aplicación web.
    • Dominios personalizados: Admite nombres de dominio personalizados con validación de dominio flexible.
    • Sondeos de estado: La aplicación necesita una supervisión inteligente del sondeo de estado. Azure Front Door usa las respuestas del sondeo para determinar el mejor origen para enrutar las solicitudes de los clientes.
    • Compatibilidad con la supervisión: Análisis de informes integrados con un panel todo en uno que integre los patrones de Front Door y de seguridad. Puede configurar alertas que se integren con Azure Monitor. Permite que la aplicación registre cada solicitud y los sondeos de estado con errores.
    • Protección contra DDoS: Tiene protección contra DDoS de capa 3-4 integrada.
    • Red de entrega de contenido: Posiciona a Relecloud para usar una red de entrega de contenidos. La red de entrega de contenido proporciona aceleración del sitio.
  • Firewall de aplicaciones web: Utiliza Azure Web Application Firewall para proporcionar protección centralizada contra exploits y vulnerabilidades web comunes. Relecloud utilizó Azure Web Application Firewall por los siguientes motivos:

    • Protección global: Proporciona una mejor protección global de aplicaciones web sin sacrificar el rendimiento.
    • Protección contra botnets: El equipo puede supervisar y configurar los ajustes para abordar las preocupaciones de seguridad relacionadas con las redes de bots.
    • Paridad con el entorno local: La solución local se ejecutaba detrás de un firewall de aplicaciones web administrado por el departamento de TI.
    • Facilidad de uso: Web Application Firewall se integra con Azure Front Door.
  • Almacenamiento de configuración: Elija si desea añadir almacenamiento de configuración de la aplicación a su aplicación web. Azure App Configuration es un servicio para la administración central de la configuración de la aplicación y las marcas de características. Revise procedimientos recomendados de App Configuration para decidir si este servicio es una buena opción para la aplicación. Relecloud quería sustituir la configuración basada en archivos por un almacén de configuración central que se integre con la plataforma y el código de la aplicación. Agregaron App Configuration a la arquitectura por los siguientes motivos:

    • Flexibilidad: Admite marcas de características. Las marcas de características permiten a los usuarios optar por recibir o no en las características de versión preliminar anticipada de un entorno de producción sin volver a implementar la aplicación.
    • Compatibilidad con la canalización de Git: El origen de verdad para los datos de configuración debe ser un repositorio de Git. Canalización necesaria para actualizar los datos en el almacén de configuración central.
    • Compatibilidad con identidades administradas: Admite identidades administradas para simplificar y ayudar a proteger la conexión al almacén de configuración.
  • Gestor de secretos: Utilice Azure Key Vault si tiene secretos que administrar en Azure. Puede incorporar Key Vault en aplicaciones .NET mediante el objeto ConfigurationBuilder. La aplicación web local de Relecloud almacenaba secretos en archivos de configuración de código, pero es una mejor práctica de seguridad almacenar secretos en una ubicación que admita RBAC y controles de auditoría. Aunque las identidades administradas son la solución preferida para conectarse a recursos de Azure, Relecloud tenía secretos de aplicaciones que necesitaban para administrar. Relecloud usó Key Vault por los siguientes motivos:

    • Cifrado: Admite cifrado de datos en reposo y en tránsito
    • Compatibilidad con identidades administradas: Los servicios de aplicaciones pueden utilizar identidades administradas para acceder al almacén de secretos.
    • Supervisión y registro: Facilita el acceso de auditoría y genera alertas cuando cambian los secretos almacenados.
    • Integración: Proporciona integración nativa con el almacén de configuración de Azure (App Configuration) y la plataforma de hospedaje web (App Service).
  • Solución de almacenamiento: Revise las opciones de almacenamiento de Azure para elegir la solución de almacenamiento adecuada en función de sus requisitos. La aplicación web local de Relecloud tenía almacenamiento en disco montado en cada servidor web, pero el equipo quería utilizar una solución de almacenamiento de datos externa. Relecloud eligió Azure Blob Storage por los siguientes motivos:

    • Acceso seguro: La aplicación web puede eliminar los puntos de conexión para acceder al almacenamiento expuesto a la red pública de Internet con acceso anónimo.
    • Cifrado: Cifra datos en reposo y en movimiento.
    • Resistencia: Admite almacenamiento con redundancia de zona (ZRS). El almacenamiento con redundancia de zona replica los datos de Azure Storage de forma sincrónica en tres zonas de disponibilidad de Azure en la región primaria. Cada zona de disponibilidad es una ubicación física individual con alimentación, refrigeración y redes independientes. Esta configuración debería hacer que las imágenes de emisión de billetes sean resistentes a las pérdidas.
  • Seguridad de punto de conexión: Utilice Azure Vínculo Privado para acceder a soluciones de plataforma como servicio a través de un punto de conexión privado en su red virtual. El tráfico entre la red virtual y el servicio viaja por la red troncal de Microsoft. Relecloud eligió Vínculo Privado por las siguientes razones:

    • Comunicación de seguridad mejorada: Permite que la aplicación acceda de forma privada a los servicios de la plataforma Azure y reduce la superficie de red de los almacenes de datos para ayudar a protegerse frente a la pérdida de datos.
    • Esfuerzo mínimo: Los puntos de conexión privados admiten la plataforma de aplicaciones web y la plataforma de base de datos que usa la aplicación web. Ambas plataformas reflejan las configuraciones locales existentes para que el cambio sea mínimo.
  • Seguridad de red: Utilice Azure Firewall para controlar el tráfico entrante y saliente a nivel de red. Utilice Azure Bastion para conectarse a máquinas virtuales de forma segura sin exponer puertos RDP/SSH. Relecloud adoptó una topología de red de tipología radial y quería poner los servicios de seguridad de red compartidos en el hub. Azure Firewall mejora la seguridad inspeccionando todo el tráfico saliente desde los radios para aumentar la seguridad de red. Relecloud necesitaba Azure Bastion para realizar implementaciones seguras desde un host de salto en la subred de DevOps.

Guía de código

Para trasladar con éxito una aplicación web a la nube, es necesario actualizar el código de la aplicación web con el patrón Retry, el patrón Circuit-Breaker y el patrón de diseño Cache-Aside.

Diagrama que muestra la función de los patrones de diseño en la arquitectura esencial de una aplicación web fiable.

Figura 3. Función de los patrones de diseño.

Cada patrón de diseño proporciona beneficios de diseño de carga de trabajo que se alinean con uno o más pilares del marco de trabajo bien diseñado. A continuación, te ofrecemos una visión general de los patrones que deberías implementar:

  1. Patrón de reintento: El patrón de reintento administra los fallos transitorios reintentando las operaciones que pueden fallar de forma intermitente. Implemente este patrón en todas las llamadas salientes a otros servicios de Azure.

  2. Patrón Circuit Breaker: El patrón Circuit Breaker evita que una aplicación reintente operaciones que no son transitorias. Implemente este patrón en todas las llamadas salientes a otros servicios de Azure.

  3. Patrón Cache-Aside: El patrón Cache-Aside añade y recupera de una caché con más frecuencia que de un almacén de datos. Implemente este patrón en las solicitudes a la base de datos.

Modelo de diseño Fiabilidad (RE) Seguridad (SE) Optimización de costes (OC) Excelencia operativa (OE) Eficiencia del rendimiento (PE) Compatibilidad con los principios de WAF
Retry pattern (Patrón Retry) RE:07
Patrón Circuit-Breaker RE:03
RE:07
PE:07
PE:11
Patrón Cache Aside RE:05
PE:08
PE:12

Implementar el patrón Retry

Añada el patrón Reintentar al código de su aplicación para hacer frente a las interrupciones temporales del servicio. Estas interrupciones se denominan fallos transitorios. Los fallos transitorios suelen resolverse en cuestión de segundos. El patrón Retry le permite reenviar peticiones fallidas. También permite configurar los retardos de las peticiones y el número de intentos antes de conceder el fallo.

  • Utilizar mecanismos de reintento incorporados Utilice el mecanismo de reintento incorporado que tienen la mayoría de los servicios Azure para agilizar la implementación. Por ejemplo, la implementación de referencia utiliza la resiliencia de conexión en Entity Framework Core para aplicar el patrón de reintento en las solicitudes a Azure SQL Database (consulte el código siguiente).

    services.AddDbContextPool<ConcertDataContext>(options => options.UseSqlServer(sqlDatabaseConnectionString,
        sqlServerOptionsAction: sqlOptions =>
        {
            sqlOptions.EnableRetryOnFailure(
            maxRetryCount: 5,
            maxRetryDelay: TimeSpan.FromSeconds(3),
            errorNumbersToAdd: null);
        }));
    
  • Utilice bibliotecas de programación de reintentos. Para las comunicaciones HTTP, integre una biblioteca de resiliencia estándar como Polly o Microsoft.Extensions.Http.Resilience. Estas bibliotecas ofrecen mecanismos de reintento completos que son cruciales para administrar las comunicaciones con servicios web externos. Por ejemplo, la implementación de referencia utiliza Polly para aplicar el patrón Retry cada vez que el código construye un objeto que llama al objeto IConcertSearchService (consulte el código siguiente).

    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);
    }
    

Implementación del patrón de interruptor

Utilice el patrón Circuit Breaker para administrar las interrupciones del servicio que no sean fallos transitorios. El patrón Circuit Breaker impide que una aplicación intente acceder continuamente a un servicio que no responde. Libera la aplicación y evita el desperdicio de ciclos de CPU, de modo que la aplicación conserva su integridad de rendimiento para los usuarios finales.

Por ejemplo, la implementación de referencia aplica el patrón Circuit Breaker en todas las solicitudes a la API. Utiliza la lógica HandleTransientHttpError para detectar las peticiones HTTP que puede reintentar de forma segura pero limita el número de fallos agregados durante un periodo de tiempo especificado (consulte el siguiente código).

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

Implementación del patrón Cache-Aside

Añada el patrón Cache-Aside a su aplicación web para mejorar la administración de datos en memoria. El patrón asigna a la aplicación la responsabilidad de gestionar las solicitudes de datos y garantizar la coherencia entre la caché y un almacenamiento persistente, como una base de datos. Acorta los tiempos de respuesta y mejora el rendimiento, además de reducir la necesidad de aumentar la escala. También reduce la carga en el almacén de datos primario, mejorando la fiabilidad y la optimización de costes. Para implementar el patrón Cache-Aside, siga estas recomendaciones:

  • Configure la aplicación para utilizar una caché. Las aplicaciones de producción deberían utilizar Distributed Redis Cache porque mejora el rendimiento al reducir las consultas a la base de datos y permite sesiones no pegajosas para que el equilibrador de carga pueda distribuir el tráfico de forma uniforme. Por ejemplo, la implementación de referencia utiliza la caché Redis distribuida. El AddAzureCacheForRedis método configura la aplicación para utilizar Azure Cache for Redis (consulte el código siguiente).

    private void AddAzureCacheForRedis(IServiceCollection services)
    {
        if (!string.IsNullOrWhiteSpace(Configuration["App:RedisCache:ConnectionString"]))
        {
            services.AddStackExchangeRedisCache(options =>
            {
                options.Configuration = Configuration["App:RedisCache:ConnectionString"];
            });
        }
        else
        {
            services.AddDistributedMemoryCache();
        }
    }
    
  • Almacenamiento en caché de datos de alta necesidad. Aplique el patrón Cache-Aside en datos de alta necesidad para amplificar su eficacia. Use Azure Monitor para realizar un seguimiento de la CPU, la memoria y el almacenamiento de la base de datos. Estas métricas le ayudarán a determinar si puede utilizar un SKU de base de datos más pequeño tras aplicar el patrón Cache-Aside. Por ejemplo, la implementación de referencia almacena en caché datos muy necesarios para la página Próximos conciertos. El método GetUpcomingConcertsAsync extrae datos a la caché Redis desde la base de datos SQL y rellena la caché con los datos de conciertos más recientes (consulte el código siguiente).

    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>();
    }
    
  • Mantenga actualizados los datos de la memoria caché. Programe actualizaciones de caché periódicas para sincronizarse con los cambios más recientes en la base de datos. Determine la velocidad de actualización óptima en función de la volatilidad de los datos y las necesidades del usuario. Esta práctica garantiza que la aplicación use el patrón Cache-Aside para proporcionar acceso rápido y información actual. Por ejemplo, la implementación de referencia almacena los datos en caché solo durante una hora y utiliza el método CreateConcertAsync para borrar la clave de la caché cuando cambian los datos (consulte el código siguiente).

    public async Task<CreateResult> CreateConcertAsync(Concert newConcert)
    {
        database.Add(newConcert);
        await this.database.SaveChangesAsync();
        this.cache.Remove(CacheKeys.UpcomingConcerts);
        return CreateResult.SuccessResult(newConcert.Id);
    }
    
  • Aseguramiento de la coherencia de los datos. Implemente mecanismos para actualizar la memoria caché inmediatamente después de cualquier operación de escritura en la base de datos. Use actualizaciones controladas por eventos o clases de administración de datos dedicadas para garantizar la coherencia de la memoria caché. La sincronización coherente de la memoria caché con modificaciones de la base de datos es fundamental para el patrón Cache-Aside. Por ejemplo, la implementación de referencia utiliza el método UpdateConcertAsync para mantener la coherencia de los datos de la caché (consulte el código siguiente).

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

Guía de configuración

Las siguientes secciones ofrecen orientación sobre la aplicación de las actualizaciones de las configuraciones. Cada sección se ajusta a uno o varios pilares del marco de trabajo bien diseñado.

Configuración Fiabilidad (RE) Seguridad (SE) Optimización de costes (OC) Excelencia operativa (OE) Eficiencia del rendimiento (PE) Compatibilidad con los principios de WAF
Configurar la autorización de autenticación de usuarios & SE:05
OE:10
Implementación de identidades administradas SE:05
OE:10
Entornos de tamaño adecuado CO:05
CO:06
Implementación del escalado automático RE:06
CO:12
PE:05
Automatización de la implementación de recursos OE:05
Aplicar la supervisión OE:07
PE:04

Configure la autenticación y la autorización

Cuando migre aplicaciones web a Azure, configure mecanismos de autenticación y autorización de usuarios. Siga estas recomendaciones:

  • Utilice una plataforma de identidad. Utilice la plataforma Microsoft Identity para configurar la autenticación de aplicaciones web. Esta plataforma admite aplicaciones que usan un único directorio de Microsoft Entra, varios directorios de Microsoft Entra de diferentes organizaciones e identidades de Microsoft o cuentas sociales.

  • Crear un registro de aplicación. Microsoft Entra ID requiere un registro de aplicación en el inquilino principal. El registro de la aplicación garantiza que los usuarios que obtienen acceso a la aplicación web tienen identidades en el inquilino principal.

  • Utilice las características de la plataforma. Minimice la necesidad de código de autenticación personalizado utilizando las funciones de la plataforma para autenticar a los usuarios y acceder a los datos. Por ejemplo, App Service proporciona soporte de autenticación integrado, por lo que puede iniciar sesión en los usuarios y acceder a los datos escribiendo un código mínimo o ninguno en su aplicación web.

  • Haga cumplir la autorización en la aplicación. Utilice controles de acceso basados en roles (RBAC) para asignar los menores privilegios a los roles de la aplicación. Defina roles específicos para diferentes acciones de usuario para evitar solapamientos y garantizar la claridad. Asigne a los usuarios los roles adecuados y asegúrese de que solo tienen acceso a los recursos y acciones necesarios.

  • Prefiera el acceso temporal al almacenamiento. Utilice permisos temporales para protegerse contra el acceso no autorizado y las infracciones, como las firmas de acceso compartido (SAS). Utilice SAS de delegación de usuarios para maximizar la seguridad al conceder acceso temporal. Es el único SAS que utiliza credenciales de Microsoft Entra ID y no requiere una clave de cuenta de almacenamiento permanente.

  • Aplique la autorización en Azure. Utilice Azure RBAC para asignar los mínimos privilegios a las identidades de usuario. Azure RBAC determina a qué recursos de Azure pueden acceder las identidades, qué pueden hacer con esos recursos y a qué áreas tienen acceso.

  • Evite los permisos elevados permanentes. Use Microsoft Entra Privileged Identity Management para conceder acceso Just-In-Time para las operaciones con privilegios. Por ejemplo, los desarrolladores a menudo necesitan acceso de nivel de administrador para crear/eliminar bases de datos, modificar esquemas de tablas y cambiar permisos de usuario. Con el acceso Just-In-Time, las identidades de usuario reciben permisos temporales para realizar tareas privilegiadas.

Implementación de identidades administradas

Utilice identidades administradas para todos los servicios Azure que admitan identidades administradas. Una identidad administrada permite a los recursos de Azure (identidades de carga de trabajo) autenticarse e interactuar con otros servicios de Azure sin administrar credenciales. Los sistemas híbridos y heredados pueden mantener las soluciones de autenticación locales para simplificar la migración, pero deben realizar la transición a las identidades administradas lo antes posible. Para implantar identidades administradas, siga estas recomendaciones:

  • Elija el tipo adecuado de identidad administrada. Prefiera las identidades administradas asignadas por usuario cuando tenga dos o más recursos Azure que necesiten el mismo conjunto de permisos. Esta configuración es más eficaz que crear identidades administradas asignadas por el sistema para cada uno de esos recursos y asignar los mismos permisos a todos ellos. De lo contrario, utilice identidades administradas asignadas por el sistema.

  • Configure los privilegios mínimos. Utilice Azure RBAC para conceder solo los permisos que son críticos para las operaciones, como las acciones CRUD en bases de datos o el acceso a secretos. Los permisos de identidad de carga de trabajo son persistentes, por lo que no puede proporcionar permisos Just-In-Time o a corto plazo a las identidades de carga de trabajo. Si Azure RBAC no cubre un escenario específico, complemente Azure RBAC con políticas de acceso a nivel de servicio de Azure.

  • Proteja los secretos restantes. Almacene los secretos restantes en Azure Key Vault. desde Key Vault al inicio de la aplicación en lugar de durante cada solicitud HTTP. El acceso de alta frecuencia dentro de las solicitudes HTTP puede superar los límites de transacción de Key Vault. Almacene las configuraciones de las aplicaciones en Azure App Configuration.

Por ejemplo, la implementación de referencia utiliza el argumento Authentication en la cadena de conexión de la base de datos SQL para que App Service pueda conectarse a la base de datos SQL con una identidad administrada: Server=tcp:my-sql-server.database.windows.net,1433;Initial Catalog=my-sql-database;Authentication=Active Directory Default. Utiliza el argumento DefaultAzureCredential para permitir que la API web se conecte a Key Vault utilizando una identidad administrada (consulte el código siguiente).

    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());
            });
    });

Entornos de tamaño adecuado

Utilice los niveles de rendimiento (SKU) de los servicios Azure que satisfagan las necesidades de cada entorno sin excesos. Para dimensionar correctamente sus entornos, siga estas recomendaciones:

  • Evaluar los costos. Utilice la calculadora de precios de Azure para estimar el coste de cada entorno.

  • Optimice los costes de los entornos de producción. Los entornos de producción necesitan SKU que cumplan los acuerdos de nivel de servicio (SLA), las características y la escala necesarias para producción. Supervise continuamente el uso de recursos y ajuste las SKU para alinearlas con las necesidades reales de rendimiento.

  • Optimice los costes de los entornos de preproducción. Los entornos de preproducción deben utilizar recursos de menor coste, desactivar servicios innecesarios y aplicar descuentos como los precios de Azure Dev/Test. Asegúrese de que los entornos de preproducción sean lo suficientemente similares a los de producción para evitar introducir riesgos. Este equilibrio garantiza que las pruebas sigan siendo eficaces sin incurrir en costes innecesarios.

  • Defina SKU utilizando la infraestructura como código (IaC). Implemente IaC para seleccionar y implementar dinámicamente las SKU correctas en función del entorno. Este enfoque mejora la coherencia y simplifica la administración.

Por ejemplo, la implementación de referencia utiliza parámetros Bicep para desplegar niveles (SKU) más caros en el entorno de producción.

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

Implementación del escalado automático

El autoescalado garantiza que una aplicación web siga siendo resistente, receptiva y capaz de administrar cargas de trabajo dinámicas de forma eficaz. Para implementar el autoescalado, siga estas recomendaciones:

  • Automatice la escalabilidad horizontal. Utilice Autoescala de Azure para automatizar el escalado horizontal en entornos de producción. Configure reglas de autoescalado para escalar en función de métricas de rendimiento clave, de modo que su aplicación pueda administrar cargas variables.

  • Refine los desencadenadores de escalado. Comience con la utilización de la CPU como desencadenador de escalado inicial si no está familiarizado con los requisitos de escalado de su aplicación. Perfeccione sus desencadenadores de escalado para incluir otras métricas como RAM, rendimiento de red y E/S de disco. El objetivo es adaptarse al comportamiento de su aplicación web para mejorar el rendimiento.

  • Proporcione un búfer de escalabilidad horizontal. Configure los umbrales de desencadenador para que se activen antes de alcanzar la capacidad máxima. Por ejemplo, configure el escalado para que se produzca al 85 % de utilización de la CPU en lugar de esperar hasta que alcance el 100 %. Este enfoque proactivo ayuda a mantener el rendimiento y evitar posibles cuellos de botella.

Automatización de la implementación de recursos

Utilice la automatización para implementar y actualizar los recursos y el código de Azure en todos los entornos. Siga estas recomendaciones:

  • Usar la infraestructura como código. Implementar la infraestructura como código a través de pipeline de integración continua y entrega continua (CI/CD). Azure dispone de plantillas Bicep, ARM (JSON) y Terraform prediseñadas para cada recurso Azure.

  • Utilice un pipeline de integración continua y entrega continua (CI/CD). Utilice un pipeline CI/CD para implementar código desde el control de origen a los distintos entornos, como pruebas, preparación y producción. Use Azure Pipelines si está trabajando con Azure DevOps o GitHub Actions para proyectos de GitHub.

  • Integre las pruebas de unidades. Dé prioridad a la ejecución y superación de todas las pruebas unitarias dentro de su pipeline antes de cualquier implementación en App Services. Incorpore herramientas de cobertura y calidad del código como SonarQube para lograr una cobertura de pruebas exhaustiva.

  • Adopte un marco de simulación. Para las pruebas que implican punto de conexión externo, utilice marcos de simulación. Estos marcos permiten crear puntos de conexión simulados. Eliminan la necesidad de configurar puntos de conexión externos reales y garantizar condiciones de prueba uniformes en entornos.

  • Realice exámenes de seguridad. Use pruebas estáticas de seguridad de aplicaciones (SAST) para buscar errores de seguridad y errores de codificación en el código fuente. Además, realice análisis de composición de software (SCA) para examinar bibliotecas y componentes de terceros para detectar riesgos de seguridad. Las herramientas para estos análisis se integran fácilmente en GitHub y Azure DevOps.

Aplicar la supervisión

Implemente la supervisión de aplicaciones y plataformas para mejorar la excelencia operativa y la eficacia del rendimiento de su aplicación web. Para implantar la supervisión, siga estas recomendaciones:

  • Recopile telemetría de aplicaciones. Utilice la autoinstrumentación en Azure Application Insights para recopilar telemetría de aplicaciones, como rendimiento de solicitudes, duración media de solicitudes, errores y supervisión de dependencias, sin cambios en el código.

    La implementación de referencia utiliza AddApplicationInsightsTelemetry del paquete NuGet Microsoft.ApplicationInsights.AspNetCore para habilitar la recopilación de telemetría (consulte el código siguiente).

    public void ConfigureServices(IServiceCollection services)
    {
       ...
       services.AddApplicationInsightsTelemetry(Configuration["App:Api:ApplicationInsights:ConnectionString"]);
       ...
    }
    
  • Cree métricas de aplicación personalizadas. Utilice la instrumentación basada en código para la telemetría de aplicaciones personalizadas. Añada el SDK de Application Insights a su código y utilice la API de Application Insights.

    La implementación de referencia recopila telemetría sobre eventos relacionados con la actividad de los carritos. this.telemetryClient.TrackEvent cuenta los vales agregados al carro. Proporciona el nombre del evento (AddToCart) y especifica un diccionario que tiene concertId y count (consulte el código siguiente).

    this.telemetryClient.TrackEvent("AddToCart", new Dictionary<string, string> {
        { "ConcertId", concertId.ToString() },
        { "Count", count.ToString() }
    });
    
  • Supervise la plataforma. Habilite diagnósticos para todos los servicios compatibles y envíe diagnósticos al mismo destino que los registros de aplicaciones para su correlación. Los servicios Azure crean registros de plataforma automáticamente, pero solo los almacenan cuando se habilitan los diagnósticos. Habilite la configuración de diagnóstico para cada servicio que admita diagnósticos.

Realice la implementación de referencia

La implementación de referencia guía a los desarrolladores a través de una migración simulada de una aplicación ASP.NET local a Azure, destacando los cambios necesarios durante la fase de adopción inicial. Este ejemplo utiliza una aplicación de venta de entradas de conciertos para la empresa ficticia Relecloud, que vende entradas a través de su aplicación web local. Relecloud estableció los siguientes objetivos para su aplicación web:

  • Implementar cambios de código de bajo coste y alto valor
  • Alcanzar un objetivo de nivel de servicio (SLO) del 99,9 %
  • Adoptar las prácticas de DevOps
  • Crear entornos con costes optimizados
  • Mejorar la fiabilidad y la seguridad

Relecloud determinó que su infraestructura local no era una solución rentable para alcanzar estos objetivos. Decidieron que migrar su aplicación web CAMS a Azure era la forma más rentable de alcanzar sus objetivos inmediatos y futuros. La siguiente arquitectura representa el estado final de la implementación del patrón Relecloud's Reliable Web App.

Diagrama en el que se muestra la arquitectura de la implementación de referencia.Figura 3. Arquitectura de la implementación de referencia. Arquitectura de la implementación de referencia. Descargue un archivo Visio de esta arquitectura.