Patrones de observación
Sugerencia
Este contenido es un extracto del libro electrónico “Architecting Cloud Native .NET Applications for Azure” (Diseño de la arquitectura de aplicaciones .NET nativas en la nube para Azure), disponible en Documentos de .NET o como un PDF descargable y gratuito que se puede leer sin conexión.
Del mismo modo que se han desarrollado patrones para ayudar en el diseño del código en las aplicaciones, hay patrones para hacer funcionar las aplicaciones de manera confiable. Han surgido tres patrones útiles para el mantenimiento de las aplicaciones: el registro, la supervisión y las alertas.
Cuándo usar el registro
Independientemente de lo cuidadoso que se sea, las aplicaciones casi siempre se comportan de maneras inesperadas en producción. Cuando los usuarios notifican problemas con una aplicación, resulta útil poder ver lo que estaba ocurriendo en la aplicación cuando se produjo el problema. Una forma probada y eficaz de capturar información sobre lo que hace una aplicación mientras se ejecuta consiste en obligarla a anotar lo que hace. Este proceso se conoce como registro. Siempre que se produzcan errores o problemas en producción, el objetivo debería ser reproducir las condiciones en las que se produjeron los errores, en un entorno que no sea de producción. El hecho de contar con un buen registro proporciona una hoja de ruta que los desarrolladores pueden seguir para duplicar los problemas en un entorno en el que se pueda experimentar y realizar pruebas.
Desafíos asociados al registro con aplicaciones nativas de nube
En las aplicaciones tradicionales, los archivos de registro suelen almacenarse en el equipo local. De hecho, en sistemas operativos similares a Unix, hay una estructura de carpetas definida para contener los registros, normalmente en /var/log
.
Figura 7-1. Registro en un archivo en una aplicación monolítica.
La utilidad de realizar el registro en un archivo plano en una sola máquina se reduce enormemente en un entorno de nube. Es posible que las aplicaciones que producen registros no tengan acceso al disco local o que este sea altamente transitorio, ya que los contenedores se ordenan de forma aleatoria en máquinas físicas. Incluso un simple escalado vertical de aplicaciones monolíticas en varios nodos puede dificultar la localización de un archivo de registro basado en archivos.
Figura 7-2. Registro en archivos en una aplicación monolítica escalada.
Las aplicaciones nativas de nube desarrolladas mediante una arquitectura de microservicios también plantean algunos desafíos para los registradores basados en archivos. Las solicitudes de los usuarios ahora pueden abarcar varios servicios que se ejecutan en máquinas diferentes e incluir funciones sin servidor que no tienen acceso a un sistema de archivos local. Sería muy difícil correlacionar los registros de un usuario o una sesión en estos numerosos servicios y máquinas.
Figura 7-3. Registro en archivos locales en una aplicación de microservicios.
Por último, el número de usuarios de algunas aplicaciones nativas de nube es elevado. Imagine que cada usuario genera 100 líneas de mensajes de registro al iniciar sesión en una aplicación. De forma aislada, esto es fácil de administrar; pero si se multiplica por más de 100 000 usuarios, el volumen de registros es tan grande que se necesitan herramientas especializadas para admitir el uso eficaz de los registros.
Registro en aplicaciones nativas de nube
Cada lenguaje de programación tiene herramientas que permiten escribir registros y, normalmente, la sobrecarga de escribir estos registros es baja. Muchas de las bibliotecas de registro permiten registrar diferentes niveles de importancia, que se pueden ajustar en tiempo de ejecución. Por ejemplo, la biblioteca Serilog es una conocida biblioteca de registro estructurado para .NET que proporciona los siguientes niveles de registro:
- Verbose
- Depurar
- Information
- Advertencia
- Error
- Grave
Estos distintos niveles de registro proporcionan granularidad en el registro. Cuando la aplicación funciona correctamente en producción, puede configurarse de modo que registre solo mensajes importantes. Si el comportamiento de la aplicación es incorrecto, se puede aumentar el nivel de registro para que se recopilen registros más detallados. Esto equilibra el rendimiento y la facilidad de depuración.
El alto rendimiento de las herramientas de registro y la capacidad de ajustar el nivel de detalle deben animar a los desarrolladores a realizar el registro con frecuencia. Muchos están a favor de registrar la entrada y la salida de cada método. Este enfoque podría parecer excesivo, pero es poco frecuente que los desarrolladores opten por un nivel menor de registro. De hecho, no es raro realizar implementaciones con el único fin de agregar registros sobre un método problemático. Es mejor realizar demasiados registros que demasiados pocos. Algunas herramientas se pueden usar para proporcionar automáticamente este nivel de registro.
Debido a los desafíos que se asocian al uso de registros basados en archivos en aplicaciones nativas de nube, se prefieren los registros centralizados. Los registros se recopilan mediante aplicaciones y se envían a una aplicación de registro central que indexa y almacena los registros. Este tipo de sistema puede ingerir decenas de gigabytes de registros a diario.
También es útil seguir algunos procedimientos estándar al crear registros que abarquen muchos servicios. Por ejemplo, si se genera un identificador de correlación al principio de una interacción larga y se registra en cada mensaje relacionado con esa interacción, se facilita la búsqueda de todos los mensajes relacionados. Solo hay que buscar un mensaje y extraer el identificador de correlación para encontrar todos los mensajes relacionados. Otro ejemplo consiste en asegurarse de que el formato de registro es el mismo para cada servicio, independientemente del lenguaje o la biblioteca de registro que use. Esta normalización facilita la lectura de registros. En la figura 7-4 se muestra la forma en que una arquitectura de microservicios puede aprovechar el registro centralizado como parte de su flujo de trabajo.
Figura 7-4. Los registros de varios orígenes se ingieren en un almacén de registros centralizado.
Desafíos asociados a la detección y resolución de posibles problemas de estado de la aplicación
Algunas aplicaciones no son críticas. Quizá solo se usan internamente y, cuando se produce un problema, el usuario se pone en contacto con el equipo responsable y la aplicación se puede reiniciar. Aun así, los clientes suelen tener unas expectativas muy altas para las aplicaciones que consumen. Debe saber cuándo se producen problemas con la aplicación antes que los usuarios, o antes de que se lo notifiquen. De lo contrario, podría enterarse de un problema tras recibir un aluvión de publicaciones airadas en las redes sociales que se burlan de la aplicación o incluso de su organización.
Estos son algunos escenarios que debería tener en cuenta:
- Un servicio de la aplicación produce errores y se reinicia de forma continuada, lo que da lugar a respuestas lentas intermitentes.
- En algunos momentos del día, el tiempo de respuesta de la aplicación es lento.
- Después de una implementación reciente, la carga en la base de datos se ha triplicado.
Si se implementa correctamente, la supervisión puede informarle de las condiciones que provocarán problemas, lo que le permite resolver las condiciones subyacentes antes de que afecten al usuario.
Supervisión de aplicaciones nativas de nube
Algunos sistemas de registro centralizados también se encargan de recopilar telemetría, además de registros puros. Pueden recopilar métricas, como la hora a la que se ejecuta una consulta de la base de datos, el tiempo de respuesta medio de un servidor web e incluso los promedios de carga de la CPU y la presión de memoria, según lo que indique el sistema operativo. Junto con los registros, estos sistemas pueden proporcionar una visión integral del estado de los nodos del sistema y la aplicación en conjunto.
Las funcionalidades de recopilación de métricas de las herramientas de supervisión también se pueden incluir manualmente desde la aplicación. Los flujos empresariales que son de especial interés, como los usuarios nuevos que se registran o los pedidos que se realizan, se pueden instrumentar de forma que incrementen un contador del sistema de supervisión central. Este permite que las herramientas de supervisión no solo supervisen el estado de la aplicación, sino de la empresa.
Pueden construirse consultas en las herramientas de agregación de registros para buscar determinadas estadísticas o patrones, que luego se pueden mostrar como gráficos en paneles personalizados. Con frecuencia, los equipos invierten en el montaje de pantallas grandes en la pared para poder cambiar entre las diferentes estadísticas de una aplicación. De este modo, es fácil ver los problemas a medida que se producen.
Las herramientas de supervisión nativas de nube proporcionan telemetría en tiempo real e información sobre las aplicaciones, independientemente de si son aplicaciones monolíticas de un solo proceso o arquitecturas de microservicios distribuidos. Incluyen herramientas que permiten la recopilación de datos de la aplicación, así como herramientas para consultar y mostrar información sobre el estado de la aplicación.
Desafíos asociados a la reacción ante problemas críticos en aplicaciones nativas de nube
Si necesita reaccionar ante problemas de la aplicación, necesita alguna manera de alertar al personal adecuado. Este es el tercer patrón de observabilidad de aplicaciones nativas de nube, y depende del registro y la supervisión. La aplicación debe tener activado el registro para que se puedan diagnosticar los problemas y, en algunos casos, incorporarse en herramientas de supervisión. Además, necesita la supervisión para agregar en un solo lugar las métricas de la aplicación y los datos del estado. Una vez que esto se ha establecido, se pueden crear reglas que desencadenen alertas cuando determinadas métricas se encuentren fuera de los niveles aceptables.
Por lo general, las alertas se superponen a la supervisión, de modo que ciertas condiciones desencadenarán alertas para notificar problemas urgentes a los miembros del equipo. Estos son algunos escenarios que podrían requerir alertas:
- Uno de los servicios de la aplicación no responde después de que haya transcurrido un minuto de tiempo de inactividad.
- La aplicación devuelve respuestas HTTP incorrectas a más del 1 % de las solicitudes.
- El tiempo de respuesta medio de la aplicación para los puntos de conexión clave supera los 2000 ms.
Alertas en aplicaciones nativas de nube
Puede crear consultas en las herramientas de supervisión para buscar condiciones de error conocidas. Por ejemplo, las consultas podrían buscar indicaciones de código de estado HTTP 500 en los registros entrantes, lo que indica un problema en un servidor web. En cuanto se detecte una indicación, se podría enviar un correo electrónico o un SMS al propietario del servicio de origen, que puede empezar a investigar.
Aun así, un solo error 500 no suele ser suficiente para determinar que se ha producido un problema. Podría significar que un usuario ha escrito mal su contraseña o ha introducido datos con un formato incorrecto. Las consultas de alerta pueden crearse de modo que solo se activen cuando se detecte un número superior a la media de errores 500.
Uno de los patrones más perjudiciales en las alertas es desencadenar demasiadas alertas para que se investiguen. Los propietarios de los servicios pronto se volverán insensibles a los errores que ya investigaron y que descubrieron que eran benignos. Después, cuando se produzcan errores de verdad, se perderán en el ruido que generan cientos de falsos positivos. Para advertir de este peligro, es habitual contarles a los niños la fábula del pastor mentiroso. Es importante asegurarse de que las alertas que se activan indiquen un problema real.