Resistencia de la aplicación y la infraestructura

Completado

La resistencia es la capacidad de recuperarse de errores transitorios. La estrategia de recuperación de la aplicación restaura la función normal con un impacto mínimo en el usuario. Los errores pueden producirse en entornos de nube y la aplicación debe responder de manera que se minimice el tiempo de inactividad y la pérdida de datos. En una situación ideal, la aplicación controla los errores correctamente sin que el usuario sepa que ha habido un problema.

Dado que los entornos de microservicios pueden ser volátiles, diseñe las aplicaciones para que esperen y controlen errores parciales. Un error parcial, por ejemplo, puede incluir excepciones de código, interrupciones de red, procesos de servidor que no responden o errores de hardware. Incluso las actividades planeadas, como mover contenedores a otro nodo dentro de un clúster de Kubernetes, pueden producir un error transitorio.

Enfoques de resistencia

En el diseño de aplicaciones resistentes, a menudo tiene que elegir entre el fracaso rápido y la degradación gradual. Si se produce un fracaso rápido, la aplicación producirá inmediatamente un error o una excepción cuando algo va mal, en lugar de intentar recuperar o solucionar el problema. Esto permite identificar y corregir rápidamente los problemas. La degradación gradual significa que la aplicación intentará seguir funcionando con una capacidad limitada incluso cuando se produce un error en algún componente.

En las aplicaciones nativas de nube es importante que los servicios controlen los errores de manera gradual en lugar de mediante la estrategia de fracaso rápido. Dado que los microservicios son descentralizados e implementables de forma independiente, se esperan errores parciales. La estrategia de fracaso rápido permitiría que un error en un servicio quitara rápidamente los servicios dependientes, lo que reduce la resistencia general del sistema. En su lugar, los microservicios deben codificarse para prever y tolerar errores de servicio internos y externos. Esta degradación gradual permite que el sistema general siga funcionando incluso si se interrumpen algunos servicios. Las funciones críticas orientadas al usuario se pueden mantener, lo que evita una interrupción completa. La degradación gradual también permite que los servicios perturbados se recuperen o se reparen automáticamente antes de afectar al resto del sistema. Por lo tanto, para las aplicaciones basadas en microservicios, la degradación gradual se ajusta mejor a los procedimientos recomendados de resistencia, como el aislamiento de errores y la recuperación rápida. Evita que los incidentes locales se generen en cascada en todo el sistema.

Hay dos enfoques fundamentales para admitir una degradación gradual con resistencia: la aplicación y la infraestructura. Cada enfoque tiene ventajas y desventajas. Ambos enfoques pueden ser adecuados en función de la situación. En este módulo se explica cómo implementar la resistencia basada en código y la basada en infraestructura.

Resistencia basada en código

Para implementar la resistencia basada en código, .NET tiene una biblioteca de extensiones para la resistencia y el control de errores transitorios, Microsoft.Extensions.Http.Resilience.

Usa una sintaxis fluida y fácil de comprender para compilar e código de control de errores de una manera segura para subprocesos. Hay varias directivas de resistencia que definen el comportamiento de control de errores. En este módulo, aplicará las estrategias de reintento y de interruptor a las operaciones del cliente HTTP.

Estrategia de reintento

Una estrategia de reintento es exactamente lo que su nombre implica. La solicitud se vuelve a intentar después de una breve espera si se recibe una respuesta de error. El tiempo de espera aumenta con cada reintento. El aumento puede ser lineal o exponencial.

Una vez alcanzado el número máximo de reintentos, la estrategia abandona y lanza una excepción. Desde la perspectiva del usuario, la aplicación suele tardar más tiempo en completar algunas operaciones. Es posible que la aplicación tarde también algo de tiempo antes de informar al usuario de que no ha podido completar la operación.

Estrategia de disyuntor

Una estrategia de interruptor proporciona una interrupción a un servicio de destino después de un número repetido de errores, haciendo una pausa en el intento de comunicarse con él. El servicio podría estar experimentando un problema grave y no poder responder temporalmente. Después de un número definido de errores consecutivos, los intentos de conexión se pausan y se abre el circuito. Durante esta espera, las operaciones adicionales en el servicio de destino producen un error inmediatamente sin intentar conectar el servicio. Una vez transcurrido el tiempo de espera, se vuelve a intentar la operación. Si el servicio responde correctamente, el circuito se cierra y el sistema vuelve a la normalidad.

Resistencia basada en la infraestructura

Para implementar la resistencia basada en la infraestructura, puede usar una malla de servicio. Además de obtener resistencia sin cambiar el código, una malla de servicio proporciona administración del tráfico, directivas, seguridad, identidad segura y observación. La aplicación está desacoplada de estas capacidades operativas que se mueven al nivel de infraestructura.

Comparación con los enfoques basados en código

Un enfoque de resistencia basado en infraestructura puede usar una vista basada en métricas que le permita adaptarse dinámicamente a las condiciones del clúster en tiempo real. Este enfoque agrega otra dimensión a la administración del clúster, pero no agrega ningún código.

Con un enfoque basado en código:

  • Tendrá que adivinar qué parámetros de reintento y tiempo de espera son adecuados.
  • Se centra en una solicitud HTTP específica.

No hay ninguna manera razonable de responder a un error de infraestructura en el código de la aplicación. Tenga en cuenta las centenas o miles de solicitudes que se están procesando simultáneamente. Incluso un reintento con retroceso exponencial (número de solicitudes de tiempo) puede desbordar un servicio.

Por el contrario, los enfoques basados en la infraestructura no son compatibles con las aplicaciones internas. Por ejemplo, las transacciones de bases de datos complejas son invisibles para las mallas de servicio. Estas transacciones solo se pueden proteger contra errores con un enfoque basado en código.

En las próximas unidades, implementará una resistencia para una aplicación basada en un microservicio mediante la resistencia HTTP .NET en el código y una malla de servicio Linkerd.