NCache introduz Entry Processors para nos permitir executar uma função (ou “processador”) contra um conjunto de entradas de cache no lado do servidor.
Normalmente, para atualizar nossas entradas de cache, temos que “falar” com nosso servidor de cache duas vezes. Uma vez para recuperar as entradas do cache e outra para atualizá-las novamente após o processamento. Mas, com Entry Processors, atualizamos nossas entradas de cache diretamente no servidor, economizando essas viagens de rede e consumo desnecessário de recursos.
NCache executa Processadores de entrada independentemente da topologia de cache que está sendo usada. No caso de topologias particionadas, os processadores de entrada são executados nos nós que contêm nossas entradas a serem processadas.
Assim que invocamos um Entry Processor, ele processa um único item ou um conjunto deles com base na lógica que definimos. NCache executa nosso processador no cluster. Dentro de um processador de entrada, podemos:
- Retornar uma entrada de cache sem processá-la,
- Modifique uma entrada e salve-a no cache ou,
- Remover uma entrada.
Se uma entrada for bloqueada antes de executar o processador, podemos ignorar o bloqueio e acessar a entrada bloqueada para processá-la.
NCache Adicionar ao carrinho NCache Processador de entrada Implementação do processador de entrada
Comparando o processador de entrada com outras operações de cache
Processadores de entrada nos ajudam a atualizar ou limpar cache ou entradas diretamente no servidor, salvando as viagens de rede de busca e atualização de entradas de cache.
Para ver os processadores de entrada em ação, vamos escrever um aplicativo de console para carregar alguns clientes em um cache. Vamos armazenar o nome, os pontos de recompensa e a última data de compra de um cliente. E para motivar nossos clientes a comprar, vamos dobrar os pontos de recompensa de todos os clientes com compras nos últimos cinco dias. Em seguida, vamos recriar o mesmo cenário usando um processador de entrada e operações de cache em massa para ver a diferença no tempo de execução entre essas abordagens.
Antes de iniciar nosso aplicativo de exemplo, devemos ter um NCache Enterprise instância de edição em funcionamento. Os processadores de entrada estão disponíveis apenas na edição Enterprise.
1. Usando Operações de Cache em Massa
NCache oferece suporte a operações em massa para recuperar e atualizar entradas de cache simultaneamente em uma única chamada. Com operações em massa, temos melhor desempenho, pois reduzimos o número de viagens de rede ao nosso servidor de cache.
Para recuperar várias entradas de cache em massa, precisamos do GetCacheItemBulk()
com uma lista de chaves. Ele retorna os itens encontrados em um dicionário. E, para atualizar itens em massa, precisamos do InsertBulk()
método com um dicionário de itens para atualizar.
Para iniciar nossa comparação, vamos usar NCache GetCacheItemBulk()
e InsertBulk()
métodos para recuperar e atualizar entradas de cache em uma única solicitação.
No Program.cs
arquivo do nosso aplicativo Console, vamos escrever algo assim,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
using Alachisoft.NCache.Client; using RewardPoints; using RewardPoints.Shared; const string CacheName = "demoCache"; var customers = new List { new Customer(1, "Alice", DateTime.Today.AddDays(-1), 100), new Customer(2, "Bob", DateTime.Today.AddDays(-6), 5), new Customer(3, "Charlie", DateTime.Today.AddMonths(-1), 1), new Customer(4, "Daniel", DateTime.Today.AddDays(-3), 10), new Customer(5, "Earl", DateTime.Today, 20) }; var keys = customers.Select(c => c.ToCacheKey()); // Load customers into the cache ICache cache = CacheManager.GetCache(CacheName); PopulateCache(cache, customers); // Double customer points using NCache Bulk methods var retrievedItems = cache.GetCacheItemBulk(keys); var itemsToUpdate = new Dictionary<string, CacheItem>(); foreach (var item in retrievedItems) { var customer = item.Value.GetValue(); // Check if the customer has purchased anything in the last 5 days if (customer.LastPurchase >= DateTime.Today.AddDays(-5)) { var updated = customer with { Points = customer.Points * 2 }; itemsToUpdate.Add(updated.ToCacheKey(), updated.ToCacheItem()); } } cache.InsertBulk(itemsToUpdate); |
Primeiro, carregamos alguns clientes em um cache. Usamos o cache padrão “demoCache” criado durante o NCache instalação. Em seguida, recuperamos nossos clientes usando o GetCacheItemBulk()
método. Então, depois de verificar a data da última compra de cada cliente, dobramos seus pontos e colocamos todos os clientes atualizados de volta no cache.
Em vez de atualizar nossos clientes individualmente, usamos um dicionário para acumular os clientes que ganharam a recompensa. Então usamos o InsertBulk()
método com o dicionário.
Com o GetCacheItemBulk()
e InsertBulk()
métodos, reduzimos nossas viagens de rede para apenas duas. Uma chamada de rede para recuperar todos os clientes e outra para salvá-los de volta no cache.
Para obter mais detalhes sobre esses e outros métodos em massa, consulte Operações CRUD: uma visão geral.
NCache Adicionar ao carrinho Operações em Massa Visão geral das operações em massa
2. Usando um processador de entrada
Agora que usamos métodos em massa, vamos dobrar os pontos de recompensa de nossos clientes usando um processador de entrada. Algo assim,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using Alachisoft.NCache.Client; using RewardPoints; using RewardPoints.Shared; const string CacheName = "demoCache"; var customers = new List { new Customer(1, "Alice", DateTime.Today.AddDays(-1), 100), new Customer(2, "Bob", DateTime.Today.AddDays(-6), 5), new Customer(3, "Charlie", DateTime.Today.AddMonths(-1), 1), new Customer(4, "Daniel", DateTime.Today.AddDays(-3), 10), new Customer(5, "Earl", DateTime.Today, 20) }; var keys = customers.Select(c => c.ToCacheKey()); // Load customers ICache cache = CacheManager.GetCache(CacheName); PopulateCache(cache, customers); // Double customer points using Entry Processor var processor = new DoublePointsProcessor(); cache.ExecutionService.Invoke(keys, processor); |
Observe que não precisamos usar nenhum método para atualizar as entradas do cache. Apenas criamos um processador, passamos um conjunto de chaves e chamamos o Invoke()
método. Temos que atualizar os clientes dentro do próprio processador de entrada.
NCache Adicionar ao carrinho NCache Processador de entrada Implementação do processador de entrada
Configurando processadores de entrada
Para escrever um processador de entrada, precisamos criar uma classe que herde de IEntryProcessor
e usa o [Serializable]
atributo. Este é o nosso processador de entrada,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
using Alachisoft.NCache.Runtime.Processor; namespace RewardPoints.Shared; [Serializable] public class DoublePointsProcessor : IEntryProcessor { public bool IgnoreLock() => true; public object Process(IMutableEntry entry, params object[] arguments) { // Check if the cache entry is a customer and // if the customer has purchased something in the last 5 days if (entry.Key.StartsWith(nameof(Customer)) && entry.Value is Customer { LastPurchase: var lastPurchase } customer && lastPurchase >= DateTime.Today.AddDays(-5)) { // Update the customer's points var updatedCustomer = customer with { Points = customer.Points * 2 }; entry.Value = updatedCustomer; return updatedCustomer; } return false; } } |
Para atualizar uma entrada de cache em um processador, precisamos sobrescrever o Value
propriedade do entry
parâmetro com a entrada de cache atualizada.
Se um aplicativo cliente estiver bloqueando uma entrada, podemos executar o processador de entrada sobre ele usando o IgnoreLock()
método. Ele irá ignorar o bloqueio e acessar a entrada para processá-lo.
Antes de usar nosso novo processador, precisamos implantar a DLL com nosso processador e suas dependências para NCache. Podemos usar o Powershell Install-NCacheModule
cmdlet ou NCache Gerenciador de Web. Para obter instruções para implantar nosso processador de entrada usando o Web Manager, verifique Implantar provedores.
Por exemplo, vamos parar nossa instância “demoCache” e executar o Powershell Install-NCacheModule
cmdlet,
NCache Adicionar ao carrinho NCache Processador de entrada Implementação do processador de entrada
Como os processadores de entrada lidam com Falhas de operação?
Depois que um processador de entrada é executado, ele retorna uma coleção de resultados do tipo IEntryProcessorResult
. Cada resultado contém um IsSuccessful
bandeira e um Value
com o resultado de nossas modificações. Para nosso processador de entrada de amostra, o Value
a propriedade conterá false
, caso o cliente não tenha feito nenhuma compra recente, ou um cliente atualizado, caso contrário.
Se uma exceção for lançada durante a execução do processador de entrada, o IsSuccessful
bandeira será false
e os votos de Exception
propriedade será preenchida com a exceção lançada.
Para tornar nosso processador de entrada à prova de falhas, devemos lidar com possíveis exceções. Por exemplo, poderíamos obter um OperationFailedException
se houve alguma falha de conexão. Além disso, poderíamos obter um
EntryProcessorException
, neste caso, o processador de entrada não modificou nenhuma entrada de cache.
É assim que poderíamos exibir os resultados da entrada e possíveis mensagens de exceção,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
using Alachisoft.NCache.Client; using RewardPoints; using RewardPoints.Shared; const string CacheName = "demoCache"; var customers = new List { new Customer(1, "Alice", DateTime.Today.AddDays(-1), 100), new Customer(2, "Bob", DateTime.Today.AddDays(-6), 5), new Customer(3, "Charlie", DateTime.Today.AddMonths(-1), 1), new Customer(4, "Daniel", DateTime.Today.AddDays(-3), 10), new Customer(5, "Earl", DateTime.Today, 20) }; var keys = customers.Select(c => c.ToCacheKey()); // Load customers ICache cache = CacheManager.GetCache(CacheName); PopulateCache(cache, customers); try { // Double customer points using Entry Processor var processor = new DoublePointsProcessor(); var processedEntries = cache.ExecutionService.Invoke(keys, processor); foreach (IEntryProcessorResult entryResult in processedEntries) { DisplayEntryResult(entryResult); } } catch (EntryProcessorException e) { Console.WriteLine($"Error running the processor: {e.Message}"); } catch (OperationFailedException e) { Console.WriteLine($"Error connecting to the cache server: {e.Message}"); } |
Agora, vamos executar nossas três alternativas lado a lado. Eu os executei na minha máquina com NCache instalado localmente e usando 20 clientes aleatórios que gerei usando Falso. E aqui está o resultado,
Conclusão
Definitivamente, a alternativa com Processador de Entrada foi a mais rápida. Ele terminou em 12 milissegundos, enquanto aquele com métodos em massa terminou em 72 milissegundos. Com Entry Processors, notamos uma melhora de desempenho, pois economizamos todas as viagens excessivas de rede dobrando os pontos de nossos clientes diretamente no servidor.
Isso é o que são os processadores de entrada e como eles funcionam. Mesmo que não tenhamos escrito um benchmark para testar isso NCache recurso, essa comparação nos dá uma ideia de como usar os processadores de entrada. Com eles, economizamos algumas idas e vindas ao nosso NCache servidor processando nossas entradas de cache diretamente em um NCache servidor. Da próxima vez que precisar atualizar algumas das entradas de cache, experimente os processadores de entrada.
Para obter mais detalhes sobre como funcionam os Processadores de entrada, consulte Funcionamento do processador de entrada em cache.
Para acompanhar o código que escrevemos neste post, confira meu NCache Repositório de demonstração no GitHub.
NCache Adicionar ao carrinho Baixar NCache Comparação de edições