Internet Information Services

Escalar aplicaciones ASP.NET: Lecciones aprendidas

Richard Campbell

 

De un vistazo:

  • La importancia de la colaboración desarrolladores/TI
  • Descripción de las principales estrategias de escalado
  • Compartir conocimientos entre equipos
  • Acordar un conjunto básico de conocimientos

Contenido

Fundamentos del escalado
La reunión de las mentes
Lo que el equipo de red necesita saber del equipo de desarrollo
Lo que el equipo de desarrollo necesita saber del equipo de red
Volver al escalado
El bombardeo cooperativo

Como consultor, cada aplicación ASP.NET escalada correctamente con la que he trabajado ha sido el resultado de un esfuerzo colaborativo entre los desarrolladores (que la han creado) y los administradores de red (que realmente la ejecutan). Lamentablemente, no siempre resulta obvio al principio del

ciclo de vida de una aplicación que esta colaboración sea esencial. Por lo que rara vez tengo la oportunidad de participar desde el principio en el ciclo de vida de una aplicación; lo normal es hacerlo únicamente en el amargo final cuando surgen los problemas.

La verdad es que ninguna aplicación se escala de forma eficaz la primera vez, ya que es imposible que todo esté correcto de buenas a primeras. Para escalar correctamente una aplicación, es necesario comprender el modo en que se ha creado, así como el funcionamiento del entorno operativo en el que se ejecuta. Es decir, se necesita información tanto del personal de desarrollo como del de red. Sin este conocimiento compartido no se puede llegar a buen puerto.

Fundamentos del escalado

Antes de profundizar en el tema, vamos a allanar el terreno con lo que se necesita saber para escalar realmente una aplicación ASP.NET. Habitualmente se emplean dos estrategias fundamentales, especialización y distribución, y ambas se aplican en el escalado de aplicaciones ASP.NET de mayor tamaño. Además, cada truco para el escalado de la aplicación ASP.NET cambia de una u otra aplicación.

La especialización supone la separación de los elementos de la aplicación de modo que se puedan escalar independientemente. Por ejemplo, podría crear servidores de imágenes dedicados en vez de usar los mismos servidores que para la representación de las páginas ASP.NET. La configuración óptima de un servidor de imágenes difiere bastante de la de un servidor ASP.NET. Además, al separar las solicitudes de imágenes del resto de la aplicación se abre la posibilidad de usar recursos de terceros para servir las imágenes. El mismo enfoque se puede aplicar a otros archivos de recursos.

Por otro lado, la distribución implica la difusión de la aplicación simétricamente en varios servidores, lo que normalmente se denomina una granja de servidores web. Las aplicaciones ASP.NET resultan especialmente adecuadas para la distribución, ya que cada solicitud de página individual es relativamente pequeña y las interacciones de un determinado usuario son muy independientes de los demás usuarios. La distribución es realmente la manifestación de la filosofía de "escalado horizontal", donde varios servidores de rendimiento medio trabajan conjuntamente para servir a los usuarios, en vez del enfoque de "escalado vertical" en el que un servidor masivo realiza todas las tareas.

La combinación de la especialización y la distribución aumenta la eficacia, ya que sólo se pueden distribuir los elementos de la aplicación que necesitan un rendimiento adicional. Por ejemplo, si ha creado servidores de imágenes especializados pero el servicio de imágenes sigue sin ser adecuado, puede agregar servidores de imágenes en lugar de agregar servidores para toda la aplicación. Es importante tener en cuenta estas estrategias a medida que se profundiza en la mejora del rendimiento y en la escalabilidad de la aplicación ASP.NET.

La reunión de las mentes pensantes

Es muy probable que los desarrolladores y el personal de red/TI se reúnan en algún momento del ciclo de vida de una aplicación ASP.NET. Con suerte, esto sucederá antes de que se implemente la aplicación, pero a veces sólo se reúnen después de una crisis como, por ejemplo, cuando la aplicación se ejecuta de maravilla en el entorno de prueba, se envía a los usuarios y entonces se ralentiza enormemente (es en ese momento cuando se solicitan los servicios de consultores como yo).

Cuando los desarrolladores y el personal de red se reúnen, el objetivo principal es intercambiar información. Los desarrolladores poseen conocimientos clave acerca de la aplicación y el personal de red los tiene acerca del entorno operativo. Cada grupo necesita comprender los datos del otro grupo y cuanto más cerca del comienzo del ciclo de vida de la aplicación se reúnan, tanto mejor.

Esta reunión no se debe producir por primera vez durante una crisis. Sin un conocimiento básico entre los dos equipos, es muy difícil averiguar el motivo por el que la aplicación no tiene el rendimiento esperado. Además, es muy fácil estar a la defensiva y echar las culpas exclusivamente al otro equipo. Y eso nunca es cierto, ya que siempre se necesita a ambas partes para solucionar problemas de elevada complejidad.

Incluso cuando todo va viento en popa, este tipo de reunión puede ser todo un desafío. Las que he organizado normalmente empiezan con el personal de red a un lado de la mesa y el equipo de desarrollo al otro. Se miran fijamente. Mi estrategia para que fluya la conversación consiste normalmente en describir el objetivo de la reunión, en concreto un intercambio de conocimientos. No importa quién comience primero. Empezaré con lo que el equipo de red necesita saber del equipo de desarrollo.

Lo que el equipo de red necesita saber del equipo de desarrollo

Cada aplicación ASP.NET tiene sus propias peculiaridades, pero hay una serie de elementos clave que se aplican a todos los casos. Uno de ellos es el archivo web.config (consulte la figura 1). Web.config es un punto de intersección entre el equipo de desarrollo y el equipo de red. Unas veces lo configuran los desarrolladores y otras el personal de red. De cualquier manera, el contenido de web.config limita la configuración de hardware y de red y afecta directamente al modo de funcionamiento de la aplicación. El análisis de cada pequeño aspecto del archivo web.config daría para escribir un libro. La cuestión es que ambos grupos deben estudiar el archivo web.config y ponerse de acuerdo en lo que significa lo que representa la configuración, así como en las repercusiones que tendrán las distintas configuraciones en la aplicación y en el entorno.

fig01.gif

Figura 1 Archivo web.config que muestra algunas configuraciones de aplicaciones y la configuración de errores personalizados (haga clic en la imagen para ampliarla)

Por ejemplo, la sección <authorization> de web.config especifica el modo en que los usuarios se autenticarán en la aplicación y, de este modo, define una dependencia. Si la aplicación usa la autenticación de Windows®, dependerá de Active Directory®. Si usa autenticación basada en formularios, la dependencia será de un almacén de datos de cuentas de usuario. Está claro que a este tema le vendría bien una reunión.

Merece la pena tener en cuenta la sección <customErrors>, ya que afecta al modo en que el error se presenta a los usuarios. No se trata de una configuración compleja, pero una reunión podría ayudar a comprender cómo van a ser las páginas de error. Es probable que al principio del ciclo de vida colaborativo no haya páginas de error personalizadas,... una reunión más.

La sección <appSettings> de web.config puede ser particularmente importante. Normalmente los desarrolladores usan esta sección para ocultar valores globales como cadenas de conexión para bases de datos. Es un gran origen de dependencias y una parte clave en la planificación de la conmutación por error, la migración, etc. Pero como la sección <appSettings> es completamente personalizable, puede contener prácticamente de todo y es posible que sean necesarias muchas explicaciones para entender todo su contenido. En esta sección es habitual dejar huérfanos, es decir, valores que realmente no se usan en ninguna parte de la aplicación.

Aunque los desarrolladores no usen la sección <appSettings>, es posible que el personal de red/operaciones si quiera que lo hagan (tener todas las cadenas de conexión de base de datos en la sección es una forma eficaz de crear una estrategia sencilla de conmutación por error). Si el servidor de base de datos se queda inactivo, se puede insertar una cadena de sustitución que apunte a otro servidor de base de datos. Si se aprovecha esta oportunidad al principio del ciclo de desarrollo, se puede incrementar la confiabilidad y la capacidad de mantenimiento de la aplicación.

Finalmente, debe tener en cuenta un valor absolutamente clave en web.config desde el punto de vista del escalado: la etiqueta <sessionState>, que determina dónde se guardarán los datos de sesión para la aplicación. De forma predeterminada, los datos de sesión se almacenan "InProc" o en el espacio de proceso de la aplicación ASP.NET. Si los datos de sesión están configurados para proceso interno, significa que todo el equilibrio de carga debe ser "adherente": a un determinado usuario siempre le debe atender el mismo servidor, donde se encuentran los datos de sesión. Se trata de una conversación intensa entre los desarrolladores y el personal de red, porque afecta directamente al modo en que se escala y en que se realiza la conmutación por error. Hablar en un primer momento de esto puede ahorrar muchos quebraderos de cabeza a la hora de depurar la aplicación.

Cuando la conversación llegue al tema del estado de sesión, se desplazará tranquilamente hacia los requisitos de equilibrio de carga de la aplicación en general. Algunos entornos tienen hardware de equilibrio de carga dedicado con características específicas, pero si la aplicación no puede controlar estas características, no van a tener mucho sentido. Me he encontrado en situaciones en las que el equilibrio de la carga de hardware se ha usado con una aplicación ASP.NET que tenía datos de sesión en proceso. La consecuencia era la pérdida ocasional de sesiones sin explicación alguna. Parecía como si hubiera un error en la aplicación, pero no era así. En realidad se trataba de un error de configuración.

El personal de red necesita que el equipo de desarrollo le explique exactamente los esquemas de equilibrio de carga que funcionarán para la aplicación. Es en gran medida una conversación en dos sentidos acerca de los esquemas de equilibrio de carga que están disponibles y lo que puede tolerar la aplicación. Una gran ventaja de tener la conversación al principio del ciclo de vida de la aplicación es que se puede planear con antelación el cambio a un esquema de equilibrio de carga fuera de proceso sin afinidad.

Cuando una aplicación ASP.NET está lista para la implementación (o ya está en su implementación inicial), el personal de desarrollo tendrá una idea bastante clara de las áreas de la aplicación que son rápidas y las que son lentas. Y lo que es más importante es que conocerán los cuellos de botella o los posibles puntos de crisis en el sistema. Si el equipo de red/operaciones conoce los cuellos de botella, pueden prepararse con antelación para hacer frente a problemas y, tal vez, evitarlos.

Por ejemplo, una vez trabajé con una aplicación que realizaba un proceso de carga masiva de datos cada noche, durante el tiempo de inactividad de la aplicación. Los desarrolladores crearon el mecanismo de carga de datos, lo probaron y comprendieron su funcionamiento. Sabían que producía mucho estrés para la base de datos, pero se trataba de una forma efectiva de solucionar el problema.

Pero nunca le dijeron al equipo de red que se realizaba este proceso o que lo habían programado para que se ejecutara a la 1:00 a.m., exactamente la misma hora a la que se ejecutaban las copias de seguridad de base de datos. La base de datos permanecía en línea, pero se ejecutaba mucho más lentamente durante la hora de la copia de seguridad, ya que todas las transacciones que estaban enviando a la base de datos se mantenían en el registro de transacciones.

El conflicto sólo se identificó cuando se agotó el espacio en disco del volumen de registro de transacciones de base de datos, debido a la combinación simultánea de la carga de datos y de la copia de seguridad. Al cambiar la hora de la carga de datos a las 3:00 a.m., el problema se resolvió, pero sólo después de varios días de crisis.

Hablar al principio del proceso acerca de este tipo de cuestiones de carga de trabajo en la aplicación puede ahorrar muchos problemas posteriores.

Lo que el equipo de desarrollo necesita saber del equipo de red

Mi punto de partida favorito en la parte de la reunión donde el personal de red explica su mundo al personal de desarrollo es el diagrama de la red. Con demasiada frecuencia, los desarrolladores ven la red como en la figura 2, es decir, no ven ninguna red, simplemente servidores web, exploradores e Internet.

fig02.gif

Figura 2 Visión simple del desarrollador sobre la red (haga clic en la imagen para ampliarla)

La realidad, evidentemente, es mucha más compleja. Un diagrama como la figura 3 se asemeja más a la verdad, aunque esté simplificado. Al observar la figura 3, inmediatamente se plantean muchas preguntas como, por ejemplo, "cómo trabajarán los usuarios de redes privadas virtuales (VPN) con la aplicación" o "cuál es la diferencia de autenticación entre un usuario interno y otro público", etc.

fig03.gif

Figura 3 Red real que los desarrolladores deben comprender (haga clic en la imagen para ampliarla)

Evidentemente, no basta con proporcionar un diagrama de red. También es importante explicar la red en detalle porque es imposible saber, con tan solo mirar un diagrama, qué elementos afectarán a la aplicación. Es necesario hablar del proceso de conexión real de un usuario público, un usuario VPN y un usuario interno. El debate sobre las distintas reglas de firewall que existen, especialmente en arquitecturas de red de tipo DMZ más complejas, planteará de forma natural posibles problemas para la aplicación.

Evidentemente, será beneficioso tener todas estas conversaciones antes de que se haya implementado la aplicación, incluso antes de que se inicie el desarrollo; pero, a pesar de todo, la conversación se tiene que producir finalmente y es fundamental que alguien en reunión entienda perfectamente el diagrama de toda la red.

La red también es el escenario de modelos de conmutación por error y de redundancia, pero sin algún tipo de soporte técnico del software o al menos el conocimiento del comportamiento, estos modelos rara vez funcionan según lo planeado. Es necesario celebrar una reunión acerca de cómo serán los distintos escenarios de conmutación por error. El hecho de que haya clústeres en la base de datos afectará al código relacionado con el acceso a la base de datos. Por ejemplo, ¿se pueden reintentar las consultas después de un cambio de servidor? Si está disponible un sitio redundante, ¿cómo se van a replicar los datos en el sitio? ¿Cómo se realizará el cambio de un sitio a otro?

Se puede ver una vez más que una reunión al principio del proceso sirve de ayuda, si bien es verdad que más vale tarde que nunca. Todas las personas implicadas en la aplicación deben entender estas cuestiones. No hay nada más frustrante que tener una solución de conmutación por error que no funcione realmente cuando se necesita.

Por último, hay un otro recurso de red clave que se debe compartir: los registros de producción. Siempre recomiendo que los registros de producción estén disponibles para el equipo de desarrollo. La respuesta típica del personal de red ante esta solicitud es: "Pídemelos y te los enviaré". No considero que esto sea adecuado. Resulta mucho más efectivo dar a los desarrolladores la capacidad de que puedan recuperar los registros, normalmente desde un sitio de copia de seguridad.

Los registros de producción son esenciales durante una crisis. Con frecuencia constituyen la mejor (y única) fuente de datos reales y empíricos sobre lo que ha sucedido realmente. Pero también son valiosos en circunstancias más normales. Cuando los desarrolladores tienen acceso rutinario a los registros de producción, pueden consultarlos para comprobar el comportamiento de una nueva característica. Esto es una forma fantástica para averiguar que la característica no hace lo previsto y corregir el problema antes de que se convierta en una crisis. Si todo el mundo tiene acceso a los registros, se puede reaccionar más rápidamente a los problemas y corregirlos antes.

Volver al escalado

La reunión entre el equipo de red y el equipo de desarrollo gira entorno a la comprensión del alcance completo de los problemas que rodean al escalado de una aplicación ASP.NET. El entorno real en el que funciona la aplicación afecta directamente al modo en que funcionará el código que ejecuta la aplicación. Todas las estrategias de escalado afectarán a su comportamiento en el entorno. La aplicación de una estrategia de especialización, como la separación de las partes relacionadas con SSL de la aplicación, puede requerir cambios en el entorno de red y, seguramente, cambios en los propios servidores.

Incluso un cambio aparentemente centrado en el código, como el uso de almacenamiento en caché, puede afectar al entorno. Esto se debe a que al agregar el almacenamiento en caché de los datos a la aplicación ASP.NET, se reduce el número de llamadas de base de datos a cambio de un aumento en el uso de memoria. El resultado es que puede aumentar el número de servidores ASP.NET necesarios, o aumentar el número de reciclajes de subprocesos de trabajo, lo que activaría eventos de supervisión de la red.

El escalado de la aplicación ASP.NET afecta tanto al equipo de desarrollo como al de red, por lo que merece la pena que participen ambos grupos en el proceso de toma de decisiones. A menudo la colaboración dará como resultado soluciones originales que los equipos no habrían descubierto al trabajar de forma independiente. Por ejemplo, el personal de red puede darse cuenta de que existen soluciones de hardware en la compañía que pueden resultar útiles para que los desarrolladores cumplan los requisitos de rendimiento y escalado. Este tipo de oportunidades se ponen de manifiesto al hablar de los detalles de la aplicación y del entorno.

El bombardeo cooperativo

Recursos para escalar aplicaciones ASP.NET

Una crisis en el escalado no tiene porque ser algo malo. De hecho, normalmente es algo bueno ya que se produce cuando un gran número de usuarios desea ejecutar la aplicación, poniendo así a prueba el valor de la aplicación. Eso sí, hay que hacer que funcione.

En ocasiones, las crisis de escalado se producen por cualquier otro evento, tal vez su compañía está realizando una promoción o alguien ha escrito sobre usted en un blog o quizás un sitio de red social ha dirigido una gran cantidad de personas a su sitio web al mismo tiempo. De repente, se encuentra en medio de un bombardeo intentando mantener la aplicación en funcionamiento. Como habrá adivinado, lo mejor es analizar este tipo de escenarios antes de que se produzcan realmente. Así que nada mejor para cerrar la reunión entre los desarrolladores y el personal de red que una demostración de cómo la colaboración entre ambos equipos puede ayudar a una organización a superar este tipo de crisis.

La primera cuestión que surge al gestionar la crisis es "¿cómo se detecta que el sitio está sucumbiendo bajo carga?". Con demasiada frecuencia la respuesta es "tenemos una llamada del director técnico". Si la primera señal de que el sitio web tiene problemas es una llamada de alguien externo, entonces puede empezar a preocuparse. Algún sistema de medición decente debería notificarle los problemas antes de que suene el teléfono. Aunque eso no impediría que suene el teléfono, al menos le dará cierta ventaja a la hora de responder. Una respuesta del tipo "¿ah, sí?" al director técnico no es una forma de progresar profesionalmente.

Siguiente pregunta: ¿a quién se llama primero? ¿Quién responde al evento? Normalmente alguien del personal de red recibe la primera advertencia y es posible que esa persona sea relativamente inexperta, por lo que es necesario establecer un plan de escalado de problemas claro. ¿A quién se llama después? El reto es efectuar un diagnóstico rápido lo antes posible para averiguar el tipo de problema que se está produciendo. Una cosa es cuando se trata de una interrupción de la red y otra cosa bien distinta es un problema de escalado. Con los problemas de escalado, se recomienda que alguien del equipo de desarrollo intervenga lo antes posible.

Todos los implicados en el bombardeo necesitan disponer de información valiosa, por lo que los derechos de acceso efectivos son clave. El objetivo es difundir tanta información como se posible para poder efectuar un diagnóstico efectivo y esto, a la larga, debe establecer el alcance de la solución.

A menudo, si la única respuesta es escribir código, el evento habrá acabado antes de que se pueda escribir código. Evidentemente, el evento se debe tener en cuenta para modelar las prioridades de desarrollo en el futuro, pero no es razonable (ni inteligente) intentar escribir un montón de código y ponerlo en producción sin realizar pruebas cuidadosas. Regla número 1 de cualquier bombardeo: no empeorarlo.

Cuando se trata de problemas de escalado, la solución a veces consiste en esperar simplemente a que desaparezcan. Pero sigue siendo una decisión que se puede tomar.

Al mismo tiempo, la planificación de estas contingencias significa que se pueden aplicar distintas técnicas rápidamente. Resulta increíble ver el poco tiempo que demora solucionar un problema de escalado cuando trabajan conjuntamente los recursos de red y de desarrollo, incluso podrían ser lo suficientemente eficaces como para que el evento promocional previsto tenga realmente éxito.

Como conclusión, la lección aprendida por el equipo de red es que una aplicación ASP.NET de alto escalado y buen rendimiento supone una colaboración con éxito entre las personas que crean la aplicación y las que la implementan y usan.

La colaboración es inevitable, por lo que lo mejor es comenzar cuanto antes las reuniones entre los equipos para compartir información. El objetivo de las reuniones es crear conocimiento y consenso para todos los elementos de la aplicación: lo que hace, cómo funciona, de qué depende, cómo se comporta bajo carga y cómo afronta los problemas que van surgiendo a lo largo del tiempo.

Cuando se obtiene una colaboración realmente efectiva, el resultado es una compañía más ágil, con gran capacidad de respuesta ante problemas y que puede comunicar los objetivos claros acerca de lo que la aplicación necesita para tener éxito en el futuro.

Richard Campbell es director regional de Microsoft, MVP en ASP.NET y uno de los presentadores de .NET Rocks, el programa de entrevistas en Internet para desarrolladores .NET (visite dotnetrocks.com). Richard lleva años asesorando a compañías sobre el rendimiento y el escalado de ASP.NET y también es uno de los cofundadores de Strangeloop Networks.

© 2008 Microsoft Corporation y CMP Media, LLC. Reservados todos los derechos. Queda prohibida la reproducción parcial o total sin previa autorización.