.NET Core y ASP.NET Core están ganando popularidad gracias a su sencillez de diseño, ligereza, código abierto y compatibilidad con Windows y Linux. Como resultado, muchas aplicaciones existentes también están migrando de .NET Framework a .NET Core. Prácticamente todas las aplicaciones nuevas se desarrollan en .NET Core.
Muchas de estas aplicaciones .NET Core manejan un alto volumen de tráfico, atendiendo a millones de usuarios y transacciones. Por lo tanto, tienen un gran impacto en su negocio y son de suma importancia.
Las aplicaciones .NET Core que suelen requerir escalabilidad son aplicaciones de servidor que deben procesar un gran volumen de transacciones con mucha rapidez y tiempos de respuesta muy cortos. Muchas de estas aplicaciones están orientadas al cliente, lo que significa que procesan sus solicitudes. Si no responden con rapidez, el coste para la empresa es elevado en términos de pérdida de ingresos y de clientes satisfechos.
Las siguientes aplicaciones .NET Core requieren escalabilidad:
Curiosamente, todas las aplicaciones mencionadas anteriormente tienen arquitecturas de nivel de aplicación muy escalables. Cada uno de ellos le permite escalar linealmente a medida que crece su carga de transacciones agregando más servidores, máquinas virtuales o instancias de contenedores junto con un balanceador de carga.
Pero, a pesar de una arquitectura muy escalable en la capa de aplicación, las aplicaciones de servidor .NET Core se enfrentan hoy en día a importantes cuellos de botella de escalabilidad. Estos cuellos de botella se producen en diferentes áreas, como:
El principal cuello de botella para todas las aplicaciones .NET Core con alto tráfico es su base de datos. La mayoría de las aplicaciones actuales siguen utilizando bases de datos relacionales como SQL Server u Oracle. Estas bases de datos se convierten rápidamente en cuellos de botella de escalabilidad a medida que aumenta la carga de transacciones en estas aplicaciones. Esto ocurre tanto si se utiliza SQL Server en una máquina virtual como en Azure SQL Database.
Esto sucede porque una base de datos relacional no se puede particionar lógicamente como una base de datos NoSQL, sino que permanece en una única ubicación física; incluso la partición a nivel de columna no se asemeja en nada a una partición al estilo NoSQL. Por lo tanto, no es posible aumentar la capacidad de transacciones de la capa de base de datos agregando más servidores, como sí se puede hacer con una base de datos NoSQL.
Por ejemplo, mientras que su nivel de aplicación puede tener fácilmente 10, 20, 30 o más servidores de aplicaciones a medida que crece su carga de transacciones, su nivel de base de datos no puede crecer de la misma manera.
Por todo esto, su base de datos relacional se convierte en un cuello de botella de rendimiento para cualquier dato que almacene en ella (datos de aplicaciones u otros datos).
SQL Server ha introducido optimizaciones en memoria para aumentar la cantidad de transacciones por segundo. Oracle también ha proporcionado su propia versión de las tablas In-Memory.
Si bien las optimizaciones en memoria generan mejoras en el rendimiento, no abordan el problema central de la escalabilidad lineal. Las tablas en memoria generalmente se usan para datos de solo lectura y para escalar una capacidad de transacciones de solo lectura, debe agregar más instancias de SQL Server en máquinas de gama alta.
Las tablas en memoria también tienen limitaciones en el tamaño de los datos; no puede poner tablas grandes en la memoria ya que toda la tabla debe estar en la memoria. Y su replicación a otras instancias de SQL Server solo se puede realizar en otras tablas en memoria y no en una base de datos adecuada.
En resumen, estas optimizaciones en memoria de las bases de datos SQL Server y Oracle no son capaces de satisfacer completamente las necesidades de escalabilidad de su aplicación .NET Core.
Una de las razones por las que las bases de datos NoSQL se popularizaron es que ofrecen una partición de datos adecuada basada en algoritmos hash y otros. Esto resuelve muchos de los problemas de escalabilidad en la capacidad de transacciones que enfrentan las bases de datos relacionales como SQL Server y Oracle.
Sin embargo, existen razones por las que las bases de datos NoSQL no son la solución ideal para estos cuellos de botella en las bases de datos.
La solución a todos los problemas mencionados anteriormente es usar un caché distribuido en memoria como NCache en la implementación de su aplicación .NET Core. NCache Es una caché distribuida de código abierto para .NET y .NET Core, extremadamente rápida y con escalabilidad lineal. Imagínela como un almacén de datos en memoria, pero distribuido. Su funcionamiento en memoria le confiere una velocidad excepcional, mientras que su distribución le permite una escalabilidad lineal.
NCache es linealmente escalable porque crea un clúster TCP de servidores de caché de bajo costo (la misma configuración que sus servidores de aplicaciones web pero con más memoria) y agrupa los recursos de memoria y CPU de todos estos servidores en una capacidad lógica. NCache luego le permite agregar servidores de caché a este clúster en tiempo de ejecución a medida que crece la carga de transacciones. Y desde NCache Al ser totalmente en memoria, es ultrarrápido y ofrece tiempos de respuesta inferiores a un milisegundo, algo que no se puede esperar de las bases de datos relacionales ni siquiera de las bases de datos NoSQL.
Además de proporcionar escalabilidad lineal, una memoria caché distribuida como NCache replica los datos de manera inteligente para que su rendimiento no se vea comprometido mientras logra la confiabilidad de los datos en caso de que un servidor de caché se caiga.
NCache Te permite escalar tus aplicaciones .NET Core a través de lo siguiente:
El cuello de botella más importante al que se enfrentan las aplicaciones .NET Core es la "Base de datos de la aplicación". Lo bueno de NCache es que, a diferencia de las bases de datos NoSQL, NCache no le pide que deje de usar su base de datos relacional existente. Puede seguir usando SQL Server, Azure SQL Database, Oracle, etc. como su base de datos y aún lograr escalabilidad lineal usando NCache encima de su base de datos relacional. Esto es porque NCache elimina todos los cuellos de botella de escalabilidad de la base de datos relacional porque, a diferencia de su base de datos, NCache es en realidad linealmente escalable.
El almacenamiento en caché de datos de aplicaciones le permite eliminar los cuellos de botella de su base de datos. 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 el 80-90% del tráfico de la base de datos a NCache. 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.
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.
Customer Load(string custId)
{
ICache cache = CacheManager.GetCache("myCache");
string key = "Customer:CustomerID:" + custId;
Customer cust = cache.Get<Customer>(key);
if (cust == null)
{
// Item not in cache so load from db
LoadCustomerFromDb(cust);
// Add item to cache for future reference
cache.Add(key, cust);
}
return cust;
}
Figura 3: uso de caché distribuida en memoria para el almacenamiento en caché de datos de aplicaciones
Otro posible cuello de botella surge al almacenar las sesiones de ASP.NET Core en SQL Server o en MemoryCache independiente. Ambas opciones presentan importantes limitaciones en cuanto a rendimiento y escalabilidad. El almacenamiento en SQL Server no es adecuado para las sesiones de ASP.NET Core y se convierte rápidamente en un cuello de botella, al igual que ocurre con los datos de la aplicación.
NCache Es un lugar excelente para almacenar tus sesiones de ASP.NET Core porque es mucho más rápido y escalable que otras opciones de almacenamiento. NCache Es más rápido porque se ejecuta en memoria y proporciona una interfaz clave-valor donde el valor es un "objeto", como lo es una sesión de ASP.NET Core. Además, es escalable porque es una caché distribuida.
Y, NCache Además, replica de forma inteligente las sesiones de ASP.NET Core a través de sus completas topologías de almacenamiento en caché, de modo que incluso si un servidor de caché falla, no hay pérdida de datos de 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 de la sesión de ASP.NET Core, que es necesaria antes de que pueda almacenarse fuera del proceso. NCache Esto se logra mediante su función de serialización compacta dinámica, que es 10 veces más rápida que la serialización estándar de .NET y .NET Core. Puede usar esta función sin realizar ningún cambio en el código.
Puedes usar NCache como su almacén de sesión de ASP.NET Core de dos maneras.
A continuación se muestra un ejemplo de cómo puede configurar su aplicación ASP.NET Core para usar NCache Proveedor de sesión:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Specify NCache as the session provider
services.AddNCacheSession(Configuration.GetSection("NCacheSettings"));
...
}
public void Configure(IApplicationBuilder app, ...)
{
// select NCache session provider for ASP.NET Core
app.UseNCacheSession();
...
}
}
Figura 4: Complemento NCache como sesiones de ASP.NET Core
Las aplicaciones ASP.NET Core, que suelen tener contenido bastante dinámico, se enfrentan a situaciones en las que el contenido o la respuesta de algunas páginas no cambian entre varias solicitudes. Sin embargo, estas páginas deben ejecutarse cada vez que se recibe una solicitud. Esto supone una carga innecesaria para los recursos del servidor web y para todas las capas de la aplicación. Como consecuencia, esto también genera cuellos de botella en el rendimiento y limita la escalabilidad de la aplicación.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Turn on ASP.NET Core Response Cache with IDistributedCache
services.AddResponseCaching();
// Select NCache as IDistributedCache provider
services.AddNCacheDistributedCache(Configuration.GetSection("NCacheSettings"));
...
}
}
Figura 5: Complemento NCache como middleware de caché de respuesta de ASP.NET Core
Para abordar la sobrecarga de la ejecución repetitiva de páginas donde la respuesta de la página no cambia, ASP.NET Core ha proporcionado un mecanismo de almacenamiento en caché de respuestas de página llamado ASP.NET Response Cache Middleware. Y, NCache ha implementado la interfaz IDistributedCache en ASP.NET Core gracias a la cual puede integrarse sin problemas. NCache como su middleware de caché de respuesta de ASP.NET Core.
Entonces, puedes usar NCache para almacenar en caché las respuestas de las páginas de ASP.NET Core durante un cierto período de tiempo, de modo que la próxima vez que se llame a la misma página con los mismos parámetros, se pueda devolver esta respuesta almacenada en caché en lugar de ejecutar la página completa de nuevo. A continuación se muestra un ejemplo de código sobre cómo configurar NCache como su middleware de caché de respuesta de ASP.NET Core.
Si su aplicación ASP.NET Core es una aplicación web en tiempo real, lo más probable es que utilice ASP.NET Core SignalR para proporcionar dicha funcionalidad. Las aplicaciones web en tiempo real ofrecen actualizaciones frecuentes del servidor al cliente. Algunos ejemplos de este tipo de aplicaciones son los juegos, las subastas, las votaciones, las redes sociales, etc.
Si su aplicación ASP.NET Core se ejecuta en un entorno multiservidor con balanceo de carga, deberá usar un proveedor de backplane SignalR de ASP.NET Core para compartir eventos entre varios servidores web. Este backplane debe ser escalable; de lo contrario, su aplicación SignalR de ASP.NET Core comenzará a experimentar problemas de rendimiento.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Specify NCache as the ASP.NET Core SignalR Backplane
services.AddSignalR().AddNCache(ncacheOptions =>
{ ncacheOptions.CacheName = "myPartitionedCache"; });
...
}
public void Configure(IApplicationBuilder app, ...)
{
// Use SignalR in ASP.NET Core
app.UseSignalR(config => { config.MapHub<MessageHub>("/messages"); });
...
}
}
Figura 6: Complemento NCache como proveedor de backplane SignalR de ASP.NET Core
NCache ha implementado un proveedor de backplane SignalR para ASP.NET Core. NCacheEl proveedor de backplane SignalR de ASP.NET Core utiliza las características de mensajería Pub/Sub de NCache que son ultrarrápidos gracias a que se ejecutan completamente en memoria. Esto permite que su aplicación ASP.NET Core SignalR acelere la propagación de eventos SignalR entre todos los servidores web y, por consiguiente, hacia los clientes.
Y esto hace que su aplicación web en tiempo real responda mejor al entregar esas actualizaciones frecuentes a los clientes. Y puede seguir aumentando la cantidad de clientes y también agregar más servidores web sin temor a cuellos de botella en el rendimiento.
Si tu aplicación .NET Core necesita usar el sistema de mensajería Pub/Sub o eventos, lo más probable es que utilice una plataforma de mensajería Pub/Sub que no esté completamente en memoria y que, en su lugar, almacene todos los mensajes en el disco. Como resultado, esto puede convertirse fácilmente en un cuello de botella de rendimiento si tu aplicación maneja un alto volumen de transacciones.
NCache también proporciona una mensajería Pub/Sub que es súper rápida porque está completamente en memoria. Y, replica todos los mensajes a otro NCache servidor para garantizar que no se pierdan datos en caso de que un servidor se caiga.
Por lo tanto, si su aplicación .NET Core utiliza NCache como su plataforma de mensajería Pub/Sub, experimentará un rendimiento súper rápido y escalabilidad lineal porque NCache en sí mismo es linealmente escalable.
A continuación se muestra un ejemplo de cómo puede usar la mensajería Pub/Sub proporcionada por NCache en su aplicación .NET Core.
private void PublishMessage (string topicName)
{
ITopic topic = _cache.MessagingService.GetTopic(topicName);
Order order = Order.GenerateOrder<Order>();
// Publish message containing "order" with expiry
Message message = new Message(order, new TimeSpan(0, 0, 15));
topic.Publish(message, DeliveryOption.All, true);
}
private ITopicSubscription SubscribeMessage (string topicName)
{
ITopic topic = _cache.MessagingService.GetTopic(topicName);
// Subscribes to the topic. Message delivered to MessageReceivedCallback
return topic.CreateSubscription(MessageReceivedCallback);
}
static void MessageReceivedCallback(object sender, MessageEventArgs args) { ... }
Figura 7: Uso de la mensajería Pub/Sub en aplicaciones .NET Core
El principal cuello de botella de escalabilidad que tu aplicación .NET Core debe eliminar se encuentra en la base de datos. En este aspecto, tus aplicaciones pueden lograr un alto rendimiento y una escalabilidad lineal mediante el almacenamiento en caché de datos. La razón es sencilla: la mayoría de las aplicaciones .NET Core manejan grandes cantidades de datos que se transfieren constantemente desde y hacia la base de datos.
Cuando se trata del almacenamiento en caché de datos de aplicaciones, el mayor temor que tiene la gente es que el caché se vuelve obsoleto, lo que significa que contiene una versión anterior de los datos que ya ha sido modificada en la base de datos por otro usuario u otra aplicación.
Este miedo a que un caché se vuelva obsoleto es tan fuerte que la mayoría de las personas solo almacenan en caché datos de solo lectura o estáticos (datos de referencia). Sin embargo, estos datos de solo lectura son solo el 20 % de los datos totales en forma de tablas de búsqueda y otros datos de referencia. La mayor parte de los datos en la base de datos son transaccionales, incluidos clientes, cuentas, actividades, etc. Y, si no almacena en caché estos datos transaccionales, entonces no se beneficiará completamente del almacenamiento en caché.
Por lo tanto, el beneficio real del almacenamiento en caché viene si puede almacenar en caché todo tipo de datos sin temor a que el almacenamiento en caché se vuelva obsoleto. NCache proporciona una serie de características para abordar esta preocupación.
La forma más efectiva de mantener tu caché actualizada es mantenerla siempre sincronizada con tu base de datos. NCache le permite hacer esto a una variedad de bases de datos de la siguiente manera:
Cuando sincroniza su caché con SQL Server, pregunta NCache para registrarse como cliente de SQL Server y luego emitir una llamada SqlDependency junto con un conjunto de datos basado en consultas SQL. Luego, cuando SQL Server ve algún cambio en este conjunto de datos, notifica NCache sobre eso
private static void CreateSqlDependency (Product product)
{
string connectionString = "Data Source=localhost;Database=northwind;...";
// SQL stmt on which the SQL Dependency is created in SQL Server
string sqlStmt = "SELECT ProductID, ProductName, QuantityPerUnit, UnitPrice " +
"FROM dbo.PRODUCTS WHERE ProductID = " + product.Id;
CacheDependency sqlDependency = new SqlCacheDependency(connectionString, sqlStmt);
CacheItem cacheItem = new CacheItem(product) { Dependency = sqlDependency };
string key = "Product:ProductId:" + product.Id; ;
cache.Add(key, cacheItem);
}
Figura 8: uso de SqlDependency para sincronizar caché con SQL Server
A continuación, NCache elimina este elemento de la memoria caché, por lo que la próxima vez que la aplicación lo necesite, tendrá que obtener la última copia de la base de datos. Si está utilizando el controlador de lectura (ver más abajo), entonces NCache también puede recargar automáticamente la última copia de la base de datos. A continuación se muestra un ejemplo de cómo puede usar SqlDependency para sincronizar su caché con SQL Server.
La memoria caché de lectura directa es una memoria caché que puede leer datos de su base de datos llamando a un controlador de lectura directa que ha desarrollado y proporcionado a la memoria caché. Del mismo modo, una memoria caché de escritura directa puede escribir cambios de datos en su base de datos llamando a un controlador de escritura directa que ha desarrollado y proporcionado a la memoria caché. La memoria caché de escritura diferida es igual que la escritura simultánea, excepto que las actualizaciones de la base de datos se realizan de forma asíncrona.
Las opciones Read-through, Write-through y Write-behind ofrecen muchas ventajas para sus aplicaciones .NET Core, entre las que se incluyen:
A continuación se muestra un ejemplo de cómo puede utilizar la lectura completa con NCache.
// Read through handler for SQL Server
public class SqlReadThruProvider : Runtime.DatasourceProviders.IReadThruProvider
{
public void Init(IDictionary parameters, string cacheId) {}
public void Dispose() {}
// Get object from the database/data-source based on the key
public ProviderCacheItem LoadFromSource(string key) {}
// Bulk-Get objects from the database/data-source based on the keys
public IDictionary<string, ProviderCacheItem> LoadFromSource(ICollection<string> keys)
{}
}
Figura 9: uso del controlador de lectura directa con NCache
Una vez que se sienta cómodo almacenando en caché todos los datos, puede comenzar a colocar una gran cantidad de datos en un caché distribuido. Aquí puede empezar a enfrentarse a otro problema peculiar de cómo encontrar rápida y fácilmente sus datos. Dado que la mayoría de los cachés distribuidos son almacenes de clave-valor, se vuelve muy difícil realizar un seguimiento de todos sus datos solo a través de claves.
Aquí es donde NCache le proporciona una variedad de formas de encontrar rápidamente datos de su caché. Ejemplos incluyen:
A continuación se muestra un ejemplo de cómo puede utilizar consultas basadas en LINQ con NCache.
// Search the cache based on object attributes by using LINQ
IQueryable>Product< products = new NCacheQuery<Product>(_cache);
var result = from product in products
where product.Id > 10
select product;
if (result != null)
{
foreach (Product p in result1)
{
// Process each “product” fetched from the database
Console.WriteLine("ProductID : " + p.Id);
}
}
Figura 10: uso de consultas LINQ con NCache
Las aplicaciones .NET Core de alto tráfico no pueden permitirse el lujo de caerse, especialmente durante las horas pico. Para este tipo de aplicaciones, hay tres objetivos arquitectónicos realmente importantes que una buena caché distribuida en memoria como NCache cumple
Permítanme explicar cada uno a continuación.
NCache proporciona una caché de cliente que es una caché local muy cercana a su aplicación. Puede ser InProc (lo que significa que reside dentro de su proceso de solicitud) o OutProc local. De cualquier manera, proporciona un acceso muy rápido a un subconjunto de los datos almacenados en caché que su aplicación en este servidor de aplicaciones necesita en este momento. Al mismo tiempo, Client Cache permanece sincronizado con el nivel de almacenamiento en caché, por lo que cualquier dato que cambien otros usuarios o aplicaciones en el nivel de almacenamiento en caché se propaga inmediatamente a Client Cache. El cliente le permite tener la velocidad de InProc sin dejar de ser parte de un nivel de almacenamiento en caché muy escalable.
Uno de los objetivos arquitectónicos más importantes de NCache es lograr escalabilidad lineal con confiabilidad de datos a través de sus topologías de almacenamiento en caché. Aquí están algunas NCache Topologías de almacenamiento en caché que ayuden a lograr ambos objetivos.
Uno de los objetivos arquitectónicos más importantes de NCache es lograr alta disponibilidad y elasticidad de caché. Lo hace a través de las siguientes capacidades arquitectónicas:
© Copyright Alachisoft 2002 - Todos los derechos reservados. NCache es una marca registrada de Diyatech Corp.