Escalando aplicativos .NET Core para desempenho extremo

 

Introdução

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.

 

Quem precisa de escalabilidade?

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:

  1. Aplicativos Web (ASP.NET Core): Geralmente, são aplicativos voltados para o cliente, mas também podem ser aplicativos voltados para grandes empresas internamente.
  2. Serviços Web (ASP.NET Core): Eles podem fornecer APIs da Web diretamente aos clientes ou podem ser parte de outro aplicativo de alta transação contendo lógica de camada de aplicativo nesses serviços da Web.
  3. Aplicativos Web em tempo real (ASP.NET Core SignalR): São aplicações em tempo real que precisam fornecer atualizações frequentes aos seus usuários utilizando o framework SignalR do ASP.NET Core. Elas também precisam ter um desempenho rápido, já que geralmente são voltadas para o cliente.
  4. Microsserviços (.NET Core): Esta é uma nova arquitetura de aplicativo para aplicativos do lado do servidor. E, assim como os Web Services, esses microsserviços geralmente fazem parte de um aplicativo Web voltado para o cliente ou de um aplicativo Web Services voltado para o cliente. Como resultado, eles também têm requisitos de alto desempenho sob cargas de transações pesadas.
  5. Outros aplicativos de servidor (.NET Core): Há uma grande variedade de outros aplicativos de servidor que devem processar uma grande quantidade de transações muito rapidamente. Esses podem ser aplicativos de processamento em lote que lidam com vários tipos de fluxos de trabalho de back-end ou podem ser aplicativos de processamento de fluxo que consomem uma grande quantidade de dados para processamento quase em tempo real. A lista continua.
 

O problema: gargalos de 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:

  1. Bancos de dados de aplicativos (bancos de dados relacionais): Este é o maior gargalo de todos. Eu explico com mais detalhes abaixo.
  2. Armazenamento de sessão do ASP.NET Core: Se as sessões forem armazenadas no SQL Server, sua aplicação ASP.NET Core enfrentará grandes gargalos.
  3. Processamento repetitivo de páginas no ASP.NET Core: Se as mesmas páginas forem executadas repetidamente e sua saída ou resposta permanecer a mesma, será um desperdício de recursos e um gargalo de desempenho.
  4. Provedor de backplane SignalR para ASP.NET Core: Se um aplicativo da Web ao vivo usando o SignalR precisar ser dimensionado, seu provedor de backplane pode facilmente se tornar um gargalo.
  5. Mensagens do Pub/Sub (não na memória): Se sua aplicação .NET Core estiver usando mensagens Pub/Sub, é provável que ela não esteja em memória e, portanto, represente um gargalo.
Gargalos de desempenho do ASP.NET Core
Figura 1: Aplicativo ASP.NET Core enfrentando gargalos de escalabilidade
 

Gargalo do banco de dados relacional

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).

 

Otimizações na memória do servidor de banco de dados não são suficientes

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.

 

Banco de dados NoSQL não é a resposta

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.

  1. Não é um armazenamento na memória: Os bancos de dados NoSQL armazenam seus dados em disco, assim como os bancos de dados relacionais. Isso significa que, independentemente do que você faça, o baixo desempenho do disco acaba se tornando um gargalo de desempenho.
  2. Não pode ser usado na maioria das vezes: Os bancos de dados NoSQL exigem que você abandone o uso de bancos de dados relacionais, como SQL Server e Oracle, e os substitua por um banco de dados NoSQL. Isso não é possível na maioria dos casos, por razões técnicas e não técnicas. Essencialmente, seu negócio depende do seu banco de dados relacional e não pode simplesmente abandoná-lo. Consequentemente, você não consegue aproveitar ao máximo os benefícios de um banco de dados NoSQL.
 

A solução: cache distribuído na memória (NCache)

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 Implementado na empresa para .NET Core
Figura 2: NCache Implementado na empresa para .NET Core

NCache Permite dimensionar suas aplicações .NET Core através dos seguintes métodos:

  • Cache de dados do aplicativo
  • Armazenamento de sessão do ASP.NET Core
  • Middleware de cache de resposta do ASP.NET Core
  • Backplane do ASP.NET Core SignalR
  • Mensagens do Pub/Sub e eventos CQ (na memória)
  • Eventos de consulta contínua (na memória)
 

Cache de dados do aplicativo

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

 

Armazenamento de sessão do ASP.NET Core

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.

  1. IDistributedCache para sessão do ASP.NET Core: NCache implementou a interface IDistributedCache que permite conectar automaticamente NCache como seu provedor de armazenamento de sessão do ASP.NET Core. Mas esta opção tem menos recursos que a outra.
  2. NCache Provedor para sessão ASP.NET Core: NCache O ASP.NET Core também implementou seu próprio provedor de armazenamento de sessão mais completo, que você pode usar. Ele oferece mais recursos, como bloqueio adicional, tempos limite, etc.

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

 

Middleware de cache de resposta 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.

 

Backplane do ASP.NET Core SignalR

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.

 

Mensagens do Pub/Sub (na memória)

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

 

Cache de dados do aplicativo

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.

 

Mantenha o cache atualizado

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.

  1. Dados de referência versus dados transacionais

    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.

  2. Sincronizar cache com banco de dados

    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:

    1. Sincronize o cache com o SQL Server: usando SqlDependency e notificações de eventos de banco de dados
    2. Sincronizar Cache com Oracle: usando notificações de eventos OracleDependency e DB
    3. Sincronize o cache com o Cosmos DB: usando o processamento de feed de alterações do Cosmos DB
    4. Sincronizar cache com qualquer banco de dados (baseado em sondagem): utilizando NCache fornece sincronização de banco de dados baseada em pesquisa.

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.

 

Cache de leitura e gravação

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:

  1. Simplifique o código do aplicativo: Mova o código de persistência de seu aplicativo para a camada de armazenamento em cache.
  2. Recarregar itens automaticamente do banco de dados: Use Read-through na expiração ou tempo de sincronização de banco de dados.
  3. Escritas mais rápidas: Use gravações de banco de dados assíncronas com write-behind.

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

 

Pesquisar o cache

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:

  1. Dados do grupo em cache (grupo/subgrupo, tags, tags nomeadas): NCache oferece várias maneiras de agrupar seus dados logicamente e, posteriormente, buscar todo o grupo em uma chamada. Isso realmente simplifica seu gerenciamento de dados.
  2. Pesquisar dados com consultas (SQL / LINQ): Além de localizar dados com base em chamadas de API de grupo, NCache também oferece a capacidade de pesquisar dados em cache com base em atributos de objetos, grupos, tags e tags nomeadas.
  3. Pesquisas paralelas: desde NCache é distribuído por natureza, quando seu aplicativo emite uma consulta de pesquisa ou uma chamada de API de pesquisa, essa consulta é executada em paralelo em todos os servidores de cache. Em seguida, os resultados de todos os servidores são retornados à máquina cliente (ou seja, o servidor de aplicativos) onde são mesclados antes de retornar os resultados finais ao seu aplicativo. Isso realmente acelera suas pesquisas de cache.

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

 

NCache Arquitetura para Extrema Escalabilidade

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.

  1. Cache do cliente (velocidade InProc)
  2. Escalabilidade linear com replicação rápida
  3. Alta disponibilidade através do cluster dinâmico

Deixe-me explicar cada um abaixo.

 

Cache do cliente (velocidade InProc)

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.

Arquitetura de cache do cliente em NCache para velocidade InProc
Figura 11: Arquitetura de Cache do Cliente em NCache para velocidade InProc
 

Escalabilidade linear com replicação rápida

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.

  1. Cache Particionado: NCache particiona o cache com base no número de servidores de cache e atribui uma partição a cada servidor de cache. Ele também ajusta o número de partições quando você adiciona ou remove servidores de cache em tempo de execução. O particionamento é a principal maneira de garantir a escalabilidade linear porque, à medida que você adiciona mais servidores, essa topologia de armazenamento em cache aumenta o tamanho geral do armazenamento e também o poder de processamento da CPU.
  2. Cache de réplica particionada: Além do particionamento, NCache também fornece réplicas para cada partição. Essas réplicas residem em servidores de cache diferentes da própria partição para garantir que, se um servidor de cache ficar inativo junto com sua partição, a réplica ficará imediatamente disponível. Desta forma, a confiabilidade dos dados é fornecida. Ao replicar cada partição apenas uma vez em outro servidor de cache, NCache atinge a confiabilidade dos dados sem comprometer a escalabilidade linear.
Topologia de cache de réplica de partição de NCache
Figura 12: Topologia de cache de réplica de partição de NCache
 

Alta disponibilidade para 100% de tempo de atividade

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:

  1. Cluster de cache ponto a ponto com autorrecuperação: NCache constrói um cluster de servidores de cache sobre TCP/IP. Este aglomerado tem um arquitetura ponto a ponto isso significa que não há nós mestre/escravo e nenhum cluster de regra de maioria. Em vez disso, cada nó é um par igual. Isso permite NCache para lidar com situações em que qualquer nó pode ficar inativo e o cluster se ajusta automaticamente e continua em execução, e não há interrupção para seu aplicativo.
  2. Configuração dinâmica: Isso significa que você não precisa codificar coisas em arquivos de configuração. NCache propaga informações de configuração para todos os clientes de cache (ou seja, seus aplicativos) em tempo de execução.
  3. Suporte a failover de conexão: Se um servidor de cache ficar inativo, todo o cluster de cache e todos os clientes de cache poderão continuar trabalhando sem nenhuma interrupção. Os clientes de cache continuam trabalhando interagindo com outros servidores de cache no cluster.

O que fazer a seguir?

© Copyright Alachisoft 2002 - . Todos os direitos reservados. NCache é uma marca registrada da Diyatech Corp.