O .NET Core e o ASP.NET Core estão ganhando popularidade devido à sua simplicidade de design, leveza, código aberto e capacidade de serem executados tanto no Windows quanto no Linux. Como resultado, muitos aplicativos existentes também estão migrando do .NET Framework para o .NET Core. Quase todos os novos aplicativos estão sendo desenvolvidos em .NET Core.
Muitas dessas aplicações .NET Core são de alto tráfego, atendendo milhões de usuários e transações. Consequentemente, essas aplicações têm um enorme impacto nos seus negócios e, portanto, são muito importantes.
Os aplicativos .NET Core que geralmente precisam de escalabilidade são aplicativos de servidor que devem processar muitas transações rapidamente, com tempos de resposta muito curtos. Muitos desses aplicativos são voltados para o cliente, ou seja, processam solicitações de clientes. Se não atenderem às solicitações dos clientes com rapidez, o custo para a empresa é alto em termos de perda de receita e de clientes satisfeitos.
Os seguintes aplicativos .NET Core exigem escalabilidade:
Curiosamente, todos os aplicativos mencionados acima têm arquiteturas de nível de aplicativo muito escaláveis. Cada um deles permite dimensionar linearmente à medida que a carga da transação aumenta, adicionando mais servidores, VMs ou instâncias de contêiner junto com um balanceador de carga.
Mas, apesar de uma arquitetura altamente escalável na camada de aplicação, as aplicações de servidor .NET Core enfrentam hoje grandes gargalos de escalabilidade. Esses gargalos ocorrem em diferentes áreas, como:
O maior gargalo para todos os aplicativos .NET Core de alto tráfego é o banco de dados do aplicativo. A maioria dos aplicativos atuais ainda usa um banco de dados relacional como o SQL Server ou o Oracle. Esses bancos de dados rapidamente se tornam gargalos de escalabilidade à medida que a carga de transações nesses aplicativos aumenta. Isso é válido tanto para o SQL Server em uma máquina virtual quanto para o Banco de Dados SQL do Azure.
Isso ocorre porque um banco de dados relacional não pode ser particionado logicamente como um banco de dados NoSQL e, em vez disso, permanece em um único local físico; mesmo algum particionamento em nível de coluna não se assemelha a um particionamento no estilo NoSQL. Portanto, você não pode aumentar a capacidade de transação da camada de banco de dados adicionando mais servidores de banco de dados como faria com um banco de dados NoSQL.
Por exemplo, enquanto sua camada de aplicativo pode facilmente ter 10, 20, 30 ou mais servidores de aplicativos à medida que sua carga de transações aumenta, sua camada de banco de dados não pode crescer da mesma forma.
Por tudo isso, seu banco de dados relacional se torna um gargalo de desempenho para quaisquer dados armazenados nele (dados do aplicativo ou outros dados).
O SQL Server introduziu otimizações na memória para aumentar o número de transações por segundo. A Oracle também forneceu sua própria versão de tabelas In-Memory.
Embora as otimizações na memória tragam melhorias de desempenho, elas não abordam a questão central da escalabilidade linear. As tabelas na memória geralmente são usadas para dados somente leitura e, para dimensionar uma capacidade de transação somente leitura, você precisa adicionar mais instâncias do SQL Server em máquinas mais avançadas.
As tabelas na memória também têm limitações quanto ao tamanho dos dados; você não pode colocar tabelas grandes na memória, pois a tabela inteira deve ser colocada na memória. E sua replicação para outras instâncias do SQL Server só pode ser feita para outras tabelas In-Memory e não para um banco de dados adequado.
Em resumo, essas otimizações em memória nos bancos de dados SQL Server e Oracle não conseguem atender completamente às necessidades de escalabilidade do seu aplicativo .NET Core.
Um dos motivos pelos quais os bancos de dados NoSQL se tornaram populares é porque eles oferecem um particionamento adequado dos dados com base em algoritmos de hash e outros. Isso resolve muitos dos problemas de escalabilidade e capacidade de transação enfrentados por bancos de dados relacionais como SQL Server e Oracle.
No entanto, existem razões pelas quais os bancos de dados NoSQL não são a solução ideal para esses gargalos de banco de dados.
A solução para todos os problemas mencionados acima é usar um Cache Distribuído In-Memory como NCache na sua implantação de aplicação .NET Core. NCache é um cache distribuído de código aberto para .NET e .NET Core que é extremamente rápido e escalável linearmente. Pense nele como um armazenamento de dados em memória que também é distribuído. O fato de estar em memória o torna extremamente rápido e o fato de ser distribuído o torna escalável linearmente.
NCache é linearmente escalável porque cria um cluster TCP de servidores de cache de baixo custo (mesma configuração dos servidores de aplicativos Web, mas com mais memória) e agrupa os recursos de memória e CPU de todos esses servidores em uma capacidade lógica. NCache em seguida, permite adicionar servidores de cache a esse cluster em tempo de execução à medida que a carga da transação aumenta. E desde NCache Como tudo é executado na memória, é extremamente rápido e oferece tempos de resposta inferiores a um milissegundo, algo que você não pode esperar de bancos de dados relacionais ou mesmo de bancos de dados NoSQL.
Além de fornecer escalabilidade linear, um cache distribuído como NCache replica os dados de forma inteligente para que seu desempenho não seja comprometido e, ao mesmo tempo, alcance a confiabilidade dos dados caso algum servidor de cache fique inativo.
NCache Permite dimensionar suas aplicações .NET Core através dos seguintes métodos:
O gargalo mais importante enfrentado pelas aplicações .NET Core é o "Banco de Dados da Aplicação". A grande vantagem disso é que... NCache é que, ao contrário dos bancos de dados NoSQL, NCache não pede que você pare de usar seu banco de dados relacional existente. Você pode continuar usando SQL Server, Banco de Dados SQL do Azure, Oracle, etc. como seu banco de dados e ainda obter escalabilidade linear usando NCache no topo de seu banco de dados relacional. Isto é porque NCache remove todos os gargalos de escalabilidade do banco de dados relacional porque, diferentemente do seu banco de dados, NCache é realmente linearmente escalável.
O Application Data Caching permite que você remova os gargalos do banco de dados. NCache permite armazenar em cache os dados do aplicativo e reduzir essas viagens caras ao banco de dados. Você pode esperar desviar 80-90% do tráfego de banco de dados para NCache. Isso reduz a pressão em seu banco de dados e permite que ele tenha um desempenho mais rápido e lide com cargas de transações maiores sem diminuir a velocidade.
O cache de dados de aplicativos significa que você armazena em cache quaisquer dados de aplicativos obtidos de seu banco de dados relacional. Isso geralmente está na forma de objetos de domínio (também chamados de entidades). Aqui está um exemplo de como usar um cache distribuído como NCache para cache de dados do aplicativo.
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: como usar o cache distribuído na memória para o cache de dados do aplicativo
Outro possível gargalo surge se você armazenar suas sessões do ASP.NET Core no SQL Server ou em um MemoryCache independente. Ambas as opções apresentam grandes limitações em termos de desempenho e escalabilidade. O armazenamento do SQL Server não é adequado para sessões do ASP.NET Core e rapidamente se torna um gargalo, assim como ocorre com os dados do aplicativo.
NCache É um ótimo lugar para armazenar suas sessões do ASP.NET Core, pois é muito mais rápido e escalável do que outras opções de armazenamento. NCache É mais rápido porque funciona na memória e fornece uma interface de chave-valor, onde o valor é um "objeto", que é o caso de uma sessão do ASP.NET Core. Além disso, é escalável porque é um cache distribuído.
E, NCache Além disso, replica de forma inteligente as sessões do ASP.NET Core por meio de suas robustas topologias de cache, de modo que, mesmo se um servidor de cache falhar, não haverá perda de dados da sessão. Essa replicação é necessária porque NCache fornece um armazenamento na memória e a memória viola o armazenamento.
NCache Além disso, acelera a serialização da sessão do ASP.NET Core, que é necessária antes que ela possa ser armazenada fora do processo. NCache Isso é possível graças ao recurso de Serialização Compacta Dinâmica, que é 10 vezes mais rápido que a serialização padrão do .NET e do .NET Core. Você pode usar esse recurso sem precisar fazer nenhuma alteração no código.
Você pode usar NCache como seu armazenamento de sessão do ASP.NET Core de duas maneiras.
Abaixo, segue um exemplo de como você pode configurar seu aplicativo ASP.NET Core para usar NCache Provedor de sessão:
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: Plug-in NCache como sessões do ASP.NET Core
Aplicações ASP.NET Core, que geralmente possuem conteúdo bastante dinâmico, enfrentam situações em que o conteúdo ou a resposta de algumas páginas não se alteram entre múltiplas requisições. No entanto, essas páginas ainda precisam ser executadas a cada requisição. Isso sobrecarrega desnecessariamente os recursos do servidor web e todas as camadas da aplicação, resultando em gargalos de desempenho e limitando a escalabilidade do aplicativo.
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: Plug-in NCache como middleware de cache de resposta do ASP.NET Core
Para lidar com a sobrecarga da execução repetitiva de páginas cuja resposta não se altera, o ASP.NET Core fornece um mecanismo de cache de respostas de página chamado ASP.NET Response Cache Middleware. NCache O ASP.NET Core implementou a interface IDistributedCache, o que permite a integração perfeita com outros sistemas. NCache como seu middleware de cache de resposta do ASP.NET Core.
Então você pode usar NCache Para armazenar em cache as respostas das páginas ASP.NET Core por um determinado período, de forma que, na próxima vez que a mesma página for chamada com os mesmos parâmetros, essa resposta em cache possa ser retornada em vez de executar a página inteira novamente. Abaixo está um exemplo de código de como configurar isso. NCache como seu middleware de cache de resposta do ASP.NET Core.
Se sua aplicação ASP.NET Core for uma aplicação web em tempo real, é muito provável que esteja utilizando o SignalR do ASP.NET Core para fornecer esse comportamento em tempo real. Aplicações web em tempo real fornecem atualizações de alta frequência do servidor para o cliente. Exemplos dessas aplicações incluem jogos, leilões, votações, redes sociais, etc.
Se sua aplicação ASP.NET Core estiver sendo executada em um ambiente com balanceamento de carga e vários servidores, ela precisará usar um provedor de backplane do SignalR para ASP.NET Core a fim de compartilhar eventos entre vários servidores web. Além disso, esse backplane precisa ser escalável. Caso contrário, sua aplicação ASP.NET Core SignalR começará a apresentar gargalos de desempenho.
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: Plug-in NCache como provedor de backplane SignalR do ASP.NET Core
NCache Implementou um provedor de backplane SignalR para ASP.NET Core. NCacheO provedor de backplane SignalR do ASP.NET Core utiliza os recursos de mensagens Pub/Sub do NCache que são extremamente rápidas por serem totalmente executadas em memória. Isso permite que seu aplicativo ASP.NET Core SignalR acelere a propagação de eventos SignalR entre todos os servidores web e, consequentemente, para os clientes.
E isso torna seu aplicativo da Web em tempo real mais responsivo ao fornecer essas atualizações frequentes aos clientes. E você pode continuar aumentando o número de clientes e também adicionar mais servidores da Web sem temer gargalos de desempenho.
Se sua aplicação .NET Core precisa usar o mecanismo de mensagens Pub/Sub ou eventos, é muito provável que esteja utilizando uma plataforma de mensagens Pub/Sub que não seja totalmente em memória e, em vez disso, armazene todas as mensagens em disco. Como resultado, isso pode facilmente se tornar um gargalo de desempenho se sua aplicação tiver um alto volume de transações.
NCache também fornece um Pub/Sub Messaging que é super-rápido porque é totalmente in-memory. E, ele replica todas as mensagens para outro NCache servidor para garantir que não haja perda de dados no caso de qualquer servidor ficar inativo.
Portanto, se o seu aplicativo .NET Core usar NCache como sua plataforma Pub/Sub Messaging, ele terá desempenho super-rápido e escalabilidade linear porque NCache em si é linearmente escalável.
Veja abaixo um exemplo de como você pode usar o Pub/Sub Messaging fornecido por NCache em sua aplicação .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: Usando mensagens Pub/Sub em aplicativos .NET Core
O maior gargalo de escalabilidade que sua aplicação .NET Core precisa eliminar está no banco de dados da aplicação. Nesse aspecto, suas aplicações podem alcançar alto desempenho e escalabilidade linear por meio do cache de dados. A razão para isso é simples: a maioria das aplicações .NET Core lida com um grande volume de dados transferidos entre o banco de dados e a aplicação.
Quando se trata de cache de dados de aplicativos, o maior medo que as pessoas têm é que o cache fique obsoleto, o que significa que contém uma versão mais antiga dos dados que já foram alterados no banco de dados por outro usuário ou outro aplicativo.
Esse medo de um cache se tornar obsoleto é tão forte que a maioria das pessoas armazena apenas dados somente leitura ou estáticos (dados de referência). Mas, esses dados somente leitura são apenas 20% do total de dados na forma de tabelas de pesquisa e outros dados de referência. A maior parte dos dados no banco de dados é transacional, incluindo clientes, contas, atividades, etc. E, se você não armazenar em cache esses dados transacionais, não se beneficiará totalmente do armazenamento em cache.
Portanto, o benefício real do armazenamento em cache vem se você puder armazenar em cache todos os tipos de dados sem o medo de que o armazenamento em cache fique obsoleto. NCache fornece uma série de recursos para resolver essa preocupação.
A maneira mais eficaz de manter seu cache atualizado é mantê-lo sempre sincronizado com seu banco de dados. NCache permite fazer isso com uma variedade de bancos de dados da seguinte forma:
Ao sincronizar seu cache com o SQL Server, você pergunta NCache para se registrar como cliente do SQL Server e, em seguida, emitir uma chamada SqlDependency junto com um conjunto de dados baseado em consulta SQL. Então, quando o SQL Server vê alguma alteração neste conjunto de dados, ele notifica NCache sobre isso
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: Usando SqlDependency para sincronizar o cache com o SQL Server
Em seguida, NCache remove este item do cache para que na próxima vez que o aplicativo precisar dele, ele tenha que buscar a cópia mais recente do banco de dados. Se você estiver usando o manipulador de leitura (veja abaixo), então NCache também pode recarregar automaticamente a última cópia do banco de dados para você. Abaixo está um exemplo de como você pode usar SqlDependency para sincronizar seu cache com o SQL Server.
Read-through Cache é um cache capaz de ler dados do seu banco de dados chamando um Readthrough Handler que você desenvolveu e forneceu ao cache. Da mesma forma, um cache de gravação pode gravar alterações de dados em seu banco de dados chamando um manipulador de gravação que você desenvolveu e forneceu ao cache. Cache Write-behind é o mesmo que Write-through, exceto que as atualizações do banco de dados são feitas de forma assíncrona.
Os recursos de leitura direta (read-through), gravação direta (write-through) e gravação em segundo plano (write-behind) oferecem muitos benefícios para seus aplicativos .NET Core, incluindo:
Abaixo está um exemplo de como você pode usar Read-through com 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: Usando o manipulador de leitura com NCache
Quando estiver confortável com o armazenamento em cache de todos os dados, você poderá começar a colocar muitos dados em um cache distribuído. Aqui você pode começar a enfrentar outro problema peculiar de como encontrar seus dados de maneira rápida e fácil. Como a maioria dos caches distribuídos são armazenamentos de valores-chave, fica muito difícil acompanhar todos os seus dados apenas por meio de chaves.
Aqui é onde NCache fornece várias maneiras de encontrar rapidamente dados do seu cache. Exemplos incluem:
Abaixo está um exemplo de como você pode usar consultas baseadas em LINQ com 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: Usando consultas LINQ com NCache
Aplicações .NET Core com alto tráfego não podem se dar ao luxo de ficar indisponíveis, especialmente durante os horários de pico. Para esses tipos de aplicações, existem três objetivos arquitetônicos muito importantes que um bom cache distribuído em memória, como NCache cumpre.
Deixe-me explicar cada um abaixo.
NCache fornece um Client Cache que é um cache local muito próximo ao seu aplicativo. Pode ser InProc (o que significa que reside dentro do seu processo de inscrição) ou OutProc local. De qualquer forma, ele fornece acesso muito rápido a um subconjunto dos dados armazenados em cache que seu aplicativo neste servidor de aplicativos precisa no momento. O Cache do Cliente ao mesmo tempo permanece sincronizado com a camada de armazenamento em cache para que quaisquer dados alterados por outros usuários ou aplicativos na camada de armazenamento em cache sejam imediatamente propagados para o Cache do Cliente. O cliente permite que você tenha velocidade InProc enquanto ainda faz parte de uma camada de cache muito escalável.
Um dos objetivos arquitetônicos mais importantes da NCache é alcançar escalabilidade linear com confiabilidade de dados por meio de suas topologias de armazenamento em cache. Aqui estão alguns NCache Topologias de cache que ajudam a alcançar esses dois objetivos.
Um dos objetivos arquitetônicos mais importantes da NCache é alcançar alta disponibilidade e elasticidade de cache. Ele faz isso por meio dos seguintes recursos de arquitetura:
© Copyright Alachisoft 2002 - . Todos os direitos reservados. NCache é uma marca registrada da Diyatech Corp.