NCache introduce Entry Processors per consentirci di eseguire una funzione (o "processore") rispetto a una serie di voci di memorizzazione nella cache sul lato server.
Di solito, per aggiornare le nostre voci di cache, dobbiamo "parlare" due volte con il nostro server di cache. Una volta per recuperare le voci dalla cache e un'altra per aggiornarle dopo averle elaborate. Ma, con gli Entry Processor, aggiorniamo le nostre voci della cache direttamente sul server, risparmiando questi viaggi di rete e il consumo non necessario di risorse.
NCache esegue gli Entry Processor indipendentemente dalla topologia di memorizzazione nella cache utilizzata. Nel caso di topologie partizionate, gli Entry Processor vengono eseguiti sui nodi che contengono le nostre voci da elaborare.
Una volta invocato un Entry Processor, elabora un singolo elemento o un insieme di essi in base alla logica che abbiamo definito. NCache esegue il nostro processore attraverso il cluster. All'interno di un processore di ingresso, possiamo:
- Restituisce una voce della cache senza elaborarla,
- Modificare una voce e salvarla nella cache oppure,
- Rimuovi una voce.
Se una voce è bloccata prima di eseguire il processore, possiamo ignorare il blocco e accedere alla voce bloccata per elaborarla.
NCache Dettagli NCache Processore di ingresso Implementazione del processore di ingresso
Confronto del processore di voci con altre operazioni di cache
I processori di voci ci aiutano ad aggiornare o eliminare la cache o le voci direttamente sul server salvando i viaggi di rete per il recupero e l'aggiornamento delle voci della cache.
Per vedere i processori di ingresso in azione, scriviamo un'app console per caricare alcuni clienti in una cache. Memorizziamo il nome, i punti premio e la data dell'ultimo acquisto di un cliente. E per motivare i nostri clienti all'acquisto, raddoppiamo i punti premio di tutti i clienti con un acquisto negli ultimi cinque giorni. Ricreiamo quindi lo stesso scenario usando un processore di ingresso e operazioni di cache bulk per vedere la differenza nel tempo di esecuzione tra questi approcci.
Prima di iniziare la nostra applicazione di esempio, dovremmo avere un file NCache Enterprise istanza dell'edizione attiva e funzionante. Gli Entry Processor sono disponibili solo nell'edizione Enterprise.
1. Utilizzo delle operazioni di cache di massa
NCache supporta le operazioni di massa per recuperare e aggiornare le voci della cache contemporaneamente in una singola chiamata. Con le operazioni in blocco, abbiamo prestazioni migliori poiché riduciamo il numero di viaggi di rete al nostro server cache.
Per recuperare più voci della cache in blocco, abbiamo bisogno del file GetCacheItemBulk()
con un elenco di chiavi. Restituisce gli elementi trovati in un dizionario. E, per aggiornare gli articoli in blocco, abbiamo bisogno del file InsertBulk()
metodo con un dizionario di elementi da aggiornare.
Per iniziare il nostro confronto, usiamo NCache GetCacheItemBulk()
ed InsertBulk()
metodi per recuperare e aggiornare le voci della cache in una singola richiesta.
Nel Program.cs
file della nostra app Console, scriviamo qualcosa del genere,
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); |
Innanzitutto, abbiamo caricato alcuni clienti in una cache. Abbiamo utilizzato la cache "demoCache" predefinita creata durante il NCache installazione. Successivamente, abbiamo recuperato i nostri clienti utilizzando il file GetCacheItemBulk()
metodo. Poi, dopo aver verificato la data dell'ultimo acquisto di ogni cliente, abbiamo raddoppiato i suoi punti e rimesso in cache tutti i clienti aggiornati.
Invece di aggiornare i nostri clienti individualmente, abbiamo utilizzato un dizionario per accumulare i clienti che hanno vinto il premio. Poi abbiamo usato il InsertBulk()
metodo con il dizionario.
Grazie alla GetCacheItemBulk()
ed InsertBulk()
metodi, abbiamo ridotto i nostri viaggi in rete a solo due. Una chiamata di rete per recuperare tutti i clienti e un'altra per salvarli nuovamente nella cache.
Per maggiori dettagli su questi e altri metodi in blocco, controlla Operazioni CRUD: una panoramica.
NCache Dettagli Operazioni di massa Panoramica delle operazioni in blocco
2. Utilizzo di un elaboratore di voci
Ora che abbiamo utilizzato i metodi di massa, raddoppiamo i punti premio dei nostri clienti utilizzando un processore di ingresso. Qualcosa come questo,
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); |
Si noti che non è stato necessario utilizzare alcun metodo per aggiornare le voci della cache. Abbiamo solo creato un processore, passato un set di chiavi e chiamato il file Invoke()
metodo. Dobbiamo aggiornare i clienti all'interno del processore di ingresso stesso.
NCache Dettagli NCache Processore di ingresso Implementazione del processore di ingresso
Configurazione dei processori di ingresso
Per scrivere un entry processor, dobbiamo creare una classe che erediti da IEntryProcessor
e usa il [Serializable]
attributo. Questo è il nostro elaboratore di ingresso,
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; } } |
Per aggiornare una voce della cache in un processore, dobbiamo sovrascrivere il file Value
proprietà del entry
parametro con la voce della cache aggiornata.
Se un'applicazione client sta bloccando una voce, possiamo eseguire l'Entry Processor su di essa utilizzando il IgnoreLock()
metodo. Ignorerà il blocco e accederà alla voce per elaborarlo.
Prima di utilizzare il nostro nuovo processore, dobbiamo distribuire la DLL con il nostro processore e le sue dipendenze a NCache. Possiamo usare PowerShell Install-NCacheModule
cmdlet o NCache Gestore web. Per istruzioni su come implementare il nostro processore di ingresso utilizzando Web Manager, controlla Distribuire fornitori.
Ad esempio, fermiamo la nostra istanza "demoCache" ed eseguiamo PowerShell Install-NCacheModule
cmdlet,
NCache Dettagli NCache Processore di ingresso Implementazione del processore di ingresso
Come si comportano i processori di ingresso con Operazioni fallite?
Una volta eseguito, un processore voce restituisce una raccolta di risultati di tipo IEntryProcessorResult
. Ogni risultato contiene un IsSuccessful
bandiera e a Value
con il risultato delle nostre modifiche. Per il nostro processore di ingresso di esempio, il Value
property conterrà entrambi false
, se il cliente non ha effettuato acquisti recenti o un cliente aggiornato, in caso contrario.
Se viene generata un'eccezione durante l'esecuzione del processore di ingresso, il IsSuccessful
la bandiera sarà false
e la Exception
La proprietà verrà popolata con l'eccezione generata.
Per rendere il nostro processore entry-safe a prova di errore, dovremmo gestire qualsiasi potenziale eccezione. Ad esempio, potremmo ottenere un file OperationFailedException
se si è verificato un errore di connessione. Inoltre, potremmo ottenere un
EntryProcessorException
, in questo caso, il processore di voci non ha modificato alcuna voce della cache.
Questo è il modo in cui potremmo visualizzare i risultati della voce e i possibili messaggi di eccezione,
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}"); } |
Ora, eseguiamo le nostre tre alternative fianco a fianco. Li ho eseguiti sulla mia macchina con NCache installato localmente e utilizzando 20 clienti casuali che ho generato utilizzando Bogus. Ed ecco il risultato,
Conclusione
In definitiva, l'alternativa con un Entry Processor è stata la più veloce. È terminato in 12 millisecondi, mentre quello con i metodi Bulk è terminato in 72 millisecondi. Con gli Entry Processor abbiamo notato un miglioramento delle prestazioni poiché abbiamo risparmiato tutti i viaggi di rete eccessivi raddoppiando i punti dei nostri clienti direttamente sul server.
Ecco cosa sono e come funzionano gli Entry Processor. Anche se non abbiamo scritto un benchmark per testarlo NCache caratteristica, questo confronto ci dà un'idea di come utilizzare gli Entry Processor. Con loro, salviamo alcuni viaggi di andata e ritorno al nostro NCache server elaborando le nostre voci di cache direttamente in un file NCache server. La prossima volta che devi aggiornare alcune voci della cache, prova i processori di immissione.
Per maggiori dettagli su come funzionano gli Entry Processor, controlla Funzionamento del processore di ingresso nella cache.
Per seguire il codice, abbiamo scritto in questo post, controlla il mio NCache Deposito dimostrativo su GitHub.