ASP.NET se está volviendo muy popular para desarrollar aplicaciones web y muchas de estas aplicaciones son de naturaleza de alto tráfico y sirven a millones de usuarios. Como resultado, estas aplicaciones tienen un gran impacto en los negocios y, por lo tanto, son muy importantes.
Curiosamente, la arquitectura de la aplicación ASP.NET es muy escalable en el nivel de la aplicación. Y, el protocolo HTTP también es apátrida. Ambos significan que puede ejecutar su aplicación ASP.NET en una granja web con equilibrio de carga donde cada solicitud HTTP se enruta al servidor web más apropiado. Esto le permite agregar fácilmente más servidores web a su granja web a medida que aumenta el tráfico de usuarios. Y esto hace que su nivel de aplicación ASP.NET sea muy escalable. Pero, ¿qué quiero decir con escalabilidad aquí?
La escalabilidad es esencialmente la capacidad de ofrecer un alto rendimiento incluso bajo cargas máximas. Por lo tanto, si el tiempo de respuesta de la página de su aplicación ASP.NET es muy rápido con 10 usuarios y se mantiene tan rápido con 100,000 XNUMX usuarios, entonces su aplicación ASP.NET es escalable. Pero, si su tiempo de respuesta de ASP.NET se ralentiza a medida que aumenta la cantidad de usuarios, entonces su aplicación no es escalable.
A pesar de una arquitectura muy escalable en el nivel de la aplicación, las aplicaciones ASP.NET de hoy en día se enfrentan a importantes cuellos de botella de escalabilidad. Estos cuellos de botella están ocurriendo en cuatro áreas diferentes de la siguiente manera:
Permítanme explicar cada uno con más detalle a continuación.
La base de datos de aplicaciones como SQL Server u Oracle se convierte rápidamente en un cuello de botella de escalabilidad a medida que aumenta la carga de transacciones. Esto sucede porque aunque puede escalar el nivel de la base de datos comprando un servidor de base de datos más potente, no puede escalar agregando más servidores al nivel de la base de datos. Por ejemplo, es muy común ver de 10 a 20 servidores en el nivel de la aplicación, pero no puede hacer lo mismo en el nivel de la base de datos.
Además, el estado de sesión de ASP.NET debe almacenarse en algún lugar. Y, las opciones listas para usar proporcionadas por Microsoft son InProc, StateServer y SqlServer. Desafortunadamente, las tres opciones tienen problemas importantes de rendimiento y escalabilidad. InProc y StateServer lo obligan a usar sesiones pegajosas y enviar todas las solicitudes HTTP en el mismo servidor donde se creó la sesión. Si configura StateServer como un servidor independiente para evitar sesiones pegajosas, entonces StateServer se convierte en un único punto de falla y su rendimiento también se convierte en un problema importante. Y, SqlServer almacena sesiones ASP.NET en la base de datos de SQL Server como BLOB. Y existen serios problemas de rendimiento y escalabilidad con este enfoque.
ASP.NET View State es una cadena oculta codificada (a menudo de 100 KB de tamaño) que se envía al navegador del usuario como parte de la respuesta HTTP. El navegador no hace nada con él y lo devuelve al servidor web en caso de una devolución de HTTP. Esto ralentiza la respuesta de la página ASP.NET, aumenta la carga de las tarjetas de red del servidor web y también consume una gran cantidad de ancho de banda adicional. Y, como saben, el ancho de banda no es barato.
Finalmente, ASP.NET framework ejecuta una página ASP.NET contra una solicitud de usuario, incluso si la salida de la página no cambia con respecto a la solicitud anterior. Esto puede estar bien en entornos de transacciones bajas. Pero en un entorno de muchas transacciones en el que ya se están llevando todos los recursos al límite, esta ejecución adicional puede volverse bastante costosa y un cuello de botella de escalabilidad.
Como dice el dicho “la fuerza de cualquier cadena es tan fuerte como su eslabón más débil”. Por lo tanto, siempre que haya cuellos de botella de escalabilidad en cualquier lugar del entorno de la aplicación ASP.NET, toda la aplicación se ralentiza e incluso se detiene.
E, irónicamente, esto sucede bajo cargas máximas cuando se realizan los niveles más altos de actividad comercial. Por lo tanto, el impacto de cualquier ralentización o tiempo de inactividad es mucho más costoso para su empresa.
NoSQL database El movimiento comenzó como resultado de los problemas de escalabilidad en las bases de datos relacionales. NoSQL database divide los datos en varios servidores y le permite escalar horizontalmente al igual que el nivel de la aplicación.
Pero, NoSQL database requiere que abandone su base de datos relacional y coloque sus datos en un NoSQL database. Y esto es más fácil decirlo que hacerlo por una serie de razones y, de hecho, no es posible en muchos casos.
NoSQL databases no tiene la misma capacidad de gestión y búsqueda de datos que las bases de datos relacionales y quiere que almacene datos de una manera totalmente diferente a la relacional. Además, el ecosistema que rodea a las bases de datos relacionales es demasiado fuerte para que la mayoría de las empresas lo abandonen.
Como resultado, NoSQL databaseLos s son útiles solo cuando se trata de datos no estructurados. Y, la mayoría de las aplicaciones ASP.NET manejan datos de negocios predominantemente estructurados y aptos para bases de datos relacionales. Como resultado, estos datos no se pueden mover a un NoSQL database fácilmente.
E, incluso aquellos que terminan usando un NoSQL database hacerlo para un pequeño subconjunto de sus datos totales que pueden considerarse no estructurados. Y, usan NoSQL database junto con su base de datos relacional existente.
Por lo tanto, la mayoría de las veces necesitará vivir con su base de datos relacional y encontrar otra solución para sus problemas de escalabilidad. Afortunadamente, hay una solución muy viable y la discutiré a continuación.
La solución a todos los problemas mencionados anteriormente es usar caché distribuida en memoria en la implementación de su aplicación como NCache. NCache es un Caché distribuida de código abierto para .NET que es extremadamente rápido y linealmente escalable. Piense en ello como un almacén de objetos en memoria que también se distribuye. Estar en memoria lo hace extremadamente rápido y estar distribuido lo hace linealmente escalable.
Lo bueno de una caché distribuida en memoria como NCache es que no le pide que deje de usar su base de datos relacional existente. Puede usar la memoria caché encima de su base de datos relacional porque la memoria caché elimina todos los cuellos de botella de escalabilidad de la base de datos relacional.
Entonces, ¿cómo es una memoria caché distribuida en memoria? NCache más escalable que una base de datos relacional? Bien, NCache forma un grupo de servidores de caché y agrupa la CPU, la memoria y otros recursos de todos estos servidores.
Y, NCache le permite agregar servidores de caché en tiempo de ejecución sin detener el caché o la aplicación. Y esto le permite escalar linealmente su aplicación y manejar cargas de transacciones extremas. Esto es algo que no puede hacer con su base de datos relacional.
Caché distribuida en memoria como NCache escala linealmente al permitirle agregar servidores de caché al clúster de caché (el nivel de almacenamiento en caché) en tiempo de ejecución. Pero, ¿qué tipo de números de rendimiento debe esperar de una solución como NCache.
A continuación se NCache números de rendimiento. Puedes ver completo NCache punto de referencia de rendimiento haga clic aquí
Como puede ver, una caché distribuida en memoria como NCache proporciona un rendimiento de submilisegundos para lecturas y escrituras y le permite escalar su capacidad de transacciones de forma lineal simplemente agregando más servidores de caché.
Ahora veamos cómo una memoria caché distribuida en memoria como NCache resuelve varios cuellos de botella de escalabilidad mencionados anteriormente.
El almacenamiento en caché de datos de aplicaciones le permite eliminar los cuellos de botella de su base de datos. Caché distribuida en memoria como NCache le permite almacenar en caché los datos de la aplicación y reducir esos costosos viajes a la base de datos. Puede esperar desviar del 70 al 90 % del tráfico de la base de datos a la caché distribuida en memoria. Esto reduce la presión sobre su base de datos y le permite funcionar más rápido y manejar cargas de transacciones más grandes sin ralentizarse.
Customer Load(string customerId)
{
// Key format: Customer:PK:1000
string key = "Customers:CustomerID:" + customerId;
Customer cust = (Customer) _cache[key];
if (cust == null)
{ // Item not in cache so load from db
LoadCustomerFromDb(cust);
// Add item to cache for future reference
_cache.Insert(key, cust);
}
return cust;
}
Figura 4: uso de caché distribuida en memoria para el almacenamiento en caché de datos de aplicaciones
El almacenamiento en caché de datos de la aplicación significa que almacena en caché cualquier dato de la aplicación que obtenga de su base de datos relacional. Esto suele ser en forma de objetos de dominio (también llamados entidades). Aquí hay un ejemplo de cómo usar un caché distribuido como NCache para el almacenamiento en caché de datos de la aplicación.
Caché distribuida en memoria como NCache también es un gran lugar para almacenar su estado de sesión ASP.NET. Es mucho más rápido y más escalable que las tres opciones mencionadas anteriormente (InProc, StateServer y SqlServer). NCache es más rápido porque está en la memoria y proporciona una interfaz clave-valor con el valor como un "objeto" que es un estado de sesión de ASP.NET. Y es escalable porque es un caché distribuido.
Y, NCache también replica sesiones de forma inteligente a través de sus ricas topologías de almacenamiento en caché, por lo que incluso si un servidor de caché deja de funcionar, no hay pérdida de datos de la sesión. Esta replicación es necesaria porque NCache proporciona un almacenamiento en memoria y la memoria viola el almacenamiento.
NCache también acelera la serialización del objeto de estado de sesión de ASP.NET que se requiere antes de que pueda almacenarse fuera del proceso. NCache hace esto mediante el uso de su función de serialización compacta dinámica que es 10 veces más rápida que la serialización .NET normal. Puede utilizar esta función sin realizar ningún cambio en el código.
puedes enchufar NCache Proveedor de estado de sesión (SSP) a su aplicación ASP.NET haciendo algunos cambios en su archivo web.config como se muestra a continuación.
<system.web>
...
<assemblies>
<add assembly="Alachisoft.NCache.SessionStoreProvider, Version=4.3.0.0,
Culture=neutral, PublicKeyToken=CFF5926ED6A53769" />
</assemblies>
<sessionState cookieless="false" regenerateExpiredSessionId="true"
mode="Custom" customProvider="NCacheSessionProvider"
timeout="20">
<providers>
<add name="NCacheSessionProvider"
type="Alachisoft.NCache.Web.SessionState.NSessionStoreProvider"
useInProc="false" cacheName="myDistributedCache"
enableLogs="false“ writeExceptionsToEventLog="false” />
</providers>
</sessionState>
...
</system.web>
Figura 5: Complemento NCache como proveedor de estado de sesión (SSP) de ASP.NET en Web.Config
Ya he descrito cómo ASP.NET View State es una cadena codificada enviada por el servidor web al navegador del usuario que luego la devuelve al servidor web en caso de una devolución de HTTP. Pero, con la ayuda de un caché distribuido de InMemory como NCache, puedes guardar esto en caché ASP.NET View State en el servidor y solo envíe una pequeña identificación única en su lugar.
NCache ha implementado un ASP.NET View State módulo de almacenamiento en caché a través de un adaptador de página ASP.NET personalizado y ASP.NET PageStatePersister. De esta manera, NCache intercepta tanto la solicitud como la respuesta HTTP. En el momento de la respuesta, NCache elimina la porción de "valor" de la cadena codificada y la almacena en caché y, en su lugar, coloca un identificador único (una clave de caché) en este "valor".
Luego, cuando llega la próxima solicitud HTTP, la intercepta nuevamente y reemplaza el identificador único con la cadena codificada real que ha colocado en el caché anteriormente. De esta forma, la página ASP.NET no nota nada diferente y usa la cadena codificada que contiene el estado de vista como lo hacía antes.
El siguiente ejemplo muestra un ASP.NET View State cadena codificada sin almacenamiento en caché y también lo que sucede cuando se incorpora el almacenamiento en caché.
//ASP.NET View State without Caching
<input id="__VIEWSTATE"
type="hidden"
name="__VIEWSTATE"
value="/wEPDwUJNzg0MDMxMDA1D2QWAmYPZBYCZg9kFgQCAQ9kFgICBQ9kFgJmD2QWAgIBD
xYCHhNQcm2aW91c0NvbnRyb2xNb2RlCymIAU1pY3Jvc29mdC5TaGFyZVBvaW50Lld
lYkNvbnRyb2xzLlNQQ29udHJbE1vZDA1XzRlMjJfODM3Y19kOWQ1ZTc2YmY1M2IPD
xYCHhNQcm2aW91c0NvbnRyb2xNb2RlCymIAU1pY3Jvc29mdC5TaGFyZVBvaW50Lld
lYkNvbnRyb2xzLlNQQ29udHJbE1vZDA1XzRlMjJfODM3Y19kOWQ1ZTc2YmY1M2IPD
... ==" />
//ASP.NET View State with Caching
<input id="__VIEWSTATE"
type="hidden"
name="__VIEWSTATE"
value="vs:cf8c8d3927ad4c1a84da7f891bb89185" />
Figura 6: ASP.NET View State Cadena codificada con o sin almacenamiento en caché
ASP.NET proporciona un marco de caché de resultados de ASP.NET para abordar el problema de la ejecución excesiva de páginas incluso cuando el resultado de la página no cambia. Este marco le permite almacenar en caché la salida de la página completa o de algunas partes de la página, de modo que la próxima vez que se llame a esta página, no se ejecutará y, en su lugar, se mostrará su salida en caché. Mostrar una salida ya almacenada en caché es mucho más rápido que ejecutar toda la página nuevamente.
<caching>
<outputCache defaultProvider ="NOutputCacheProvider">
<providers>
<add name="NOutputCacheProvider"
type="Alachisoft.NCache.OutputCacheProvider.NOutputCacheProvider,
Alachisoft.NCache.OutputCacheProvider, Version=x.x.x.x,
Culture=neutral, PublicKeyToken=1448e8d1123e9096"
cacheName="myDistributedCache" exceptionsEnabled="false"
writeExceptionsToEventLog="false" enableLogs="true” />"
</providers>
</outputCache>
</caching>
Figura 7: Configuración del proveedor de caché de salida de ASP.NET para NCache en Web.Config
NCache ha implementado un proveedor de caché de salida ASP.NET para .NET 4.0 o versiones posteriores. Esto le permite conectarse NCache sin problemas y sin ningún esfuerzo de programación. En caso de NCache, este proveedor es para una caché distribuida en memoria que abarca varios servidores. Por lo tanto, si su aplicación ASP.NET se ejecuta en una granja web con equilibrio de carga, la salida de la página almacenada en caché desde el servidor 1 está disponible de inmediato para todos los demás servidores de la granja web. A continuación se muestra cómo puede conectarse NCache como proveedor de caché de resultados de ASP.NET.
Las aplicaciones ASP.NET de alto tráfico no pueden darse el lujo de dejar de funcionar, especialmente durante las horas pico. Para este tipo de aplicaciones, existen tres objetivos arquitectónicos importantes que una buena caché distribuida en memoria como NCache proporciona. Ellos son:
Permítanme explicar cada área a continuación.
Uno de los objetivos arquitectónicos más importantes de NCache es lograr alta disponibilidad y elasticidad de caché. Y lo hace a través de las siguientes capacidades arquitectónicas:
Desde caché distribuida en memoria como NCache utiliza la memoria como almacén, debe proporcionar replicación de datos para garantizar la confiabilidad. Pero, al mismo tiempo, no puede comprometer la escalabilidad lineal porque esa es la razón más importante para usar un caché distribuido como NCache.
Éstos son algunos NCache Topologías de almacenamiento en caché que ayuden a lograr ambos objetivos.
Como puede ver, Partitioned-Replica Cache coloca una partición y una réplica en cada servidor de caché. Y garantiza que la réplica siempre esté en un servidor de caché diferente por motivos de confiabilidad.
He tratado de resaltar los cuellos de botella de rendimiento y escalabilidad más comunes que enfrentan las aplicaciones ASP.NET hoy en día y mostrarle cómo superarlos mediante el uso de una memoria caché distribuida en memoria como NCache. NCache es un caché distribuido de código abierto para aplicaciones .NET y Java. Por lo tanto, puede usarlo sin restricciones. Puede obtener más información sobre NCache en el siguiente enlace