.NET Core y ASP.NET Core están ganando popularidad debido a la simplicidad de su diseño, al ser livianos, de código abierto y capaces de ejecutarse tanto en Windows como en Linux. Como resultado, muchas aplicaciones existentes también se están trasladando a .NET Core del desplegable .NET Framework. Casi todas las nuevas aplicaciones se están desarrollando en .NET Core.
Muchos de estos .NET Core Las aplicaciones son de alto tráfico por naturaleza, sirviendo a millones de usuarios y transacciones. Como resultado, estas aplicaciones tienen un gran impacto en su negocio y, por lo tanto, son muy importantes.
El .NET Core Las aplicaciones que normalmente necesitan escalabilidad son aplicaciones de servidor que deben procesar muchas transacciones muy rápidamente con tiempos de respuesta muy rápidos. Muchas de estas aplicaciones están orientadas al cliente, lo que significa que están procesando las solicitudes de los clientes. Si no realizan las solicitudes de los clientes rápidamente, el costo para la empresa es alto en términos de pérdida de ingresos y pérdida de clientes satisfechos.
Siguiendo .NET Core aplicaciones requiere 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 el nivel de aplicación, .NET Core Las aplicaciones de servidor de hoy se enfrentan a importantes cuellos de botella de escalabilidad. Estos cuellos de botella están ocurriendo en diferentes áreas como:
El cuello de botella más grande para todo tráfico alto .NET Core aplicaciones es su base de datos de aplicaciones. La mayoría de las aplicaciones de hoy todavía utilizan una base de datos relacional 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 es cierto ya sea que esté usando SQL Server en una VM o Azure SQL Database.
Esto sucede porque una base de datos relacional no se puede particionar lógicamente como una NoSQL database y en su lugar se queda en una ubicación física; incluso algunas particiones a nivel de columna no se parecen en nada a una verdadera NoSQL partición de estilo. Por lo tanto, no puede aumentar la capacidad de transacción del nivel de base de datos agregando más servidores de base de datos como puede hacerlo con un NoSQL database.
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 en las bases de datos SQL Server y Oracle no pueden abordar completamente su .NET Core las necesidades de escalabilidad de la aplicación.
Una de las razones NoSQL databaseSe hicieron populares porque proporcionan una partición adecuada de los datos basada en algoritmos basados en Hash y otros. Esto resuelve muchos de los problemas de escalabilidad para la capacidad de transacción que enfrentan las bases de datos relacionales como SQL Server y Oracle.
Pero, hay razones NoSQL databaseLos correos electrónicos 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 tu .NET Core despliegue de aplicaciones. NCache es un caché distribuido de código abierto para .NET y .NET Core que es extremadamente rápido y linealmente escalable. Piense en ello como un almacén de datos en memoria que también se distribuye. Estar en memoria lo hace extremadamente rápido y estar distribuido lo hace linealmente escalable.
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 está todo en la memoria, es súper rápido y le brinda tiempos de respuesta de submilisegundos que no puede esperar de sus bases de datos relacionales o incluso NoSQL databases.
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 le permite escalar su .NET Core aplicaciones a través de lo siguiente:
El cuello de botella más importante al que se enfrenta .NET Core aplicaciones es la "Base de datos de aplicaciones". lo bueno de NCache es que a diferencia de NoSQL databases, 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 es si almacena su ASP.NET Core Sesiones en SQL Server o MemoryCache independiente. Ambas opciones tienen grandes limitaciones en cuanto a rendimiento y escalabilidad. El almacenamiento de SQL Server no es bueno para ASP.NET Core sesiones y rápidamente se convierte en un cuello de botella al igual que para los datos de la aplicación.
NCache es un gran lugar para almacenar su ASP.NET Core Sessions porque es mucho más rápido y escalable que otras opciones de almacenamiento. NCache es más rápido porque está en la memoria y proporciona una interfaz de valor clave con el valor como un "objeto" que un ASP.NET Core La sesión es. Y es escalable porque es un caché distribuido.
Y, NCache también replica inteligentemente ASP.NET Core sesiones 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 su serialización del ASP.NET Core Sesión que se requiere antes de que se pueda almacenar 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 .NET normal y .NET Core publicación por entregas. Puede utilizar esta función sin realizar ningún cambio en el código.
Puedes usar NCache como su ASP.NET Core Tienda de sesión de dos maneras.
A continuación se muestra un ejemplo de cómo puede configurar su ASP.NET Core aplicación 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 ASP.NET Core Talleres
ASP.NET Core Las aplicaciones, que por lo demás tienen un contenido bastante dinámico, enfrentan situaciones en las que, para algunas de sus páginas, el contenido o la respuesta no cambia a través de múltiples solicitudes. Pero estas páginas aún deben ejecutarse cada vez que llega la solicitud. Y esto supone una carga innecesaria para los recursos del servidor web y también para todos los niveles de esta aplicación. Como resultado, esto también aumenta los 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 ASP.NET Core Middleware de caché de respuesta
Para abordar la sobrecarga de la ejecución de páginas repetitivas donde la respuesta de la página no cambia, ASP.NET Core ha proporcionado un mecanismo de almacenamiento en caché de respuesta de página denominado ASP.NET Response Cache Middleware. Y, NCache ha implementado la interfaz IDistributedCache en ASP.NET Core por lo que puede conectar sin problemas NCache como su ASP.NET Core Middleware de caché de respuesta.
Entonces, puedes usar NCache almacenar en caché ASP.NET Core respuestas de la página 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, esta respuesta almacenada en caché se puede volver a sintonizar en lugar de ejecutar toda la página nuevamente. A continuación se muestra el código de ejemplo sobre cómo configurar NCache como su ASP.NET Core Middleware de caché de respuesta.
Si su ASP.NET Core aplicación es una aplicación web en tiempo real, entonces lo más probable es que use ASP.NET Core SignalR por proporcionar este comportamiento en tiempo real. Las aplicaciones web en tiempo real proporcionan actualizaciones de alta frecuencia desde el servidor al cliente. Los ejemplos de tales aplicaciones incluyen juegos, subastas, votaciones, redes sociales, etc.
Si su ASP.NET Core la aplicación se ejecuta en un entorno de varios servidores con equilibrio de carga, entonces tiene que usar un ASP.NET Core SignalR Backplane proveedor para compartir eventos a través de múltiples servidores web. Y, este Backplane tiene que ser escalable. De lo contrario, su ASP.NET Core La aplicación SignalR comienza a enfrentar cuellos de botella en el 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 ASP.NET Core SignalR Backplane Provider
NCache ha implementado un ASP.NET Core SignalR Backplane proveedor. NCacheASP de.NET Core SignalR Backplane el proveedor usa las funciones de mensajería Pub/Sub de NCache que son súper rápidos debido a que están totalmente en memoria. Esto permite que su ASP.NET Core Aplicación SignalR para acelerar la propagación de eventos de SignalR entre todos los servidores web y, en consecuencia, a 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 .NET Core Si la aplicación necesita usar Mensajería Pub/Sub o Eventos, lo más probable es que use una plataforma de mensajería Pub/Sub que no esté completamente en memoria y, 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 su aplicación tiene muchas 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 tu .NET Core usos de la aplicación 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 tu .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 .NET Core Apps
El mayor cuello de botella de escalabilidad que su .NET Core La aplicación debe eliminarse de la base de datos de la aplicación. En esta área, sus aplicaciones pueden lograr un alto rendimiento y escalabilidad lineal a través del almacenamiento en caché de datos de la aplicación. La razón de esto es simple. La mayoría .NET Core las aplicaciones manejan una gran cantidad de datos de ida y vuelta desde 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
Entonces, 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.
Read-through, Write-through y Write-behind proporcionan muchas ventajas a su .NET Core aplicaciones que 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
Mucho trafico .NET Core las aplicaciones no pueden darse el lujo de dejar de funcionar, especialmente durante las horas pico. Para este tipo de aplicaciones, hay tres objetivos arquitectónicos realmente importantes que una buena caché distribuida de InMemory 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: