NCache introduit les processeurs d'entrée pour nous permettre d'exécuter une fonction (ou "processeur") sur un ensemble d'entrées de mise en cache côté serveur.
Habituellement, pour mettre à jour nos entrées de cache, nous devons "parler" deux fois à notre serveur de cache. Une fois pour récupérer les entrées du cache et une autre pour les mettre à jour après les avoir traitées. Mais, avec les processeurs d'entrée, nous mettons à jour nos entrées de cache directement sur le serveur, ce qui évite ces déplacements sur le réseau et la consommation inutile de ressources.
NCache exécute les processeurs d'entrée quelle que soit la topologie de mise en cache utilisée. Dans le cas des topologies partitionnées, les processeurs d'entrée s'exécutent sur les nœuds contenant nos entrées à traiter.
Une fois que nous invoquons un processeur d'entrée, il traite un seul élément ou un ensemble d'éléments en fonction de la logique que nous avons définie. NCache exécute notre processeur sur le cluster. A l'intérieur d'un processeur d'entrée, on peut :
- Renvoyer une entrée de cache sans la traiter,
- Modifier une entrée et l'enregistrer dans le cache ou,
- Supprimer une entrée.
Si une entrée est verrouillée avant d'exécuter le processeur, nous pouvons ignorer le verrou et accéder à l'entrée verrouillée pour la traiter.
NCache Détails NCache Processeur d'entrée Implémentation du processeur d'entrée
Comparaison du processeur d'entrée avec d'autres opérations de cache
Les processeurs d'entrée nous aident à mettre à jour ou à purger le cache ou les entrées directement sur le serveur en épargnant les déplacements réseau de récupération et de mise à jour des entrées de cache.
Pour voir les processeurs d'entrée en action, écrivons une application console pour charger certains clients dans un cache. Stockons le nom, les points de récompense et la date du dernier achat d'un client. Et pour motiver nos clients à acheter, doublons les points de fidélité de tous les clients ayant effectué un achat au cours des cinq derniers jours. Ensuite, recréons le même scénario en utilisant un processeur d'entrée et des opérations de cache en bloc pour voir la différence de temps d'exécution entre ces approches.
Avant de commencer notre exemple d'application, nous devrions avoir un NCache Enterprise instance d'édition opérationnelle. Les processeurs d'entrée ne sont disponibles que dans l'édition Enterprise.
1. Utilisation des opérations de cache de masse
NCache prend en charge les opérations en bloc pour récupérer et mettre à jour les entrées de cache simultanément en un seul appel. Avec les opérations en masse, nous avons de meilleures performances puisque nous réduisons le nombre de déplacements réseau vers notre serveur de cache.
Pour récupérer plusieurs entrées de cache en bloc, nous avons besoin du GetCacheItemBulk()
avec une liste de clés. Il renvoie les éléments trouvés dans un dictionnaire. Et, pour mettre à jour les éléments en masse, nous avons besoin de InsertBulk()
méthode avec un dictionnaire d'éléments à mettre à jour.
Pour commencer notre comparaison, utilisons NCache GetCacheItemBulk()
ainsi que le InsertBulk()
méthodes pour récupérer et mettre à jour les entrées de cache en une seule requête.
Dans le Program.cs
fichier de notre application Console, écrivons quelque chose comme ça,
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); |
Tout d'abord, nous avons chargé certains clients dans un cache. Nous avons utilisé le cache "demoCache" par défaut créé lors de la NCache installation. Ensuite, nous avons récupéré nos clients en utilisant le GetCacheItemBulk()
méthode. Ensuite, après avoir vérifié la date du dernier achat de chaque client, nous avons doublé ses points et remis tous les clients mis à jour dans le cache.
Au lieu de mettre à jour nos clients individuellement, nous avons utilisé un dictionnaire pour accumuler les clients qui ont remporté la récompense. Ensuite, nous avons utilisé le InsertBulk()
méthode avec le dictionnaire.
Avec la GetCacheItemBulk()
ainsi que le InsertBulk()
méthodes, nous avons réduit nos déplacements sur le réseau à seulement deux. Un appel réseau pour récupérer tous les clients et un autre pour les sauvegarder dans le cache.
Pour plus de détails sur ces méthodes et d'autres méthodes en masse, consultez Opérations CRUD : un aperçu.
NCache Détails Opérations en vrac Présentation des opérations en masse
2. Utilisation d'un processeur d'entrée
Maintenant que nous avons utilisé les méthodes en vrac, doublons les points de récompense de nos clients à l'aide d'un processeur d'entrée. Quelque chose comme ça,
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); |
Notez que nous n'avons pas eu à utiliser de méthode pour mettre à jour les entrées du cache. Nous avons seulement créé un processeur, passé un ensemble de clés et appelé le Invoke()
méthode. Nous devons mettre à jour les clients à l'intérieur du processeur d'entrée lui-même.
NCache Détails NCache Processeur d'entrée Implémentation du processeur d'entrée
Configuration des processeurs d'entrée
Pour écrire un processeur d'entrée, nous devons créer une classe qui hérite de IEntryProcessor
et utilise le [Serializable]
attribut. Ceci est notre processeur d'entrée,
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; } } |
Pour mettre à jour une entrée de cache dans un processeur, nous devons écraser le Value
propriété du entry
paramètre avec l'entrée de cache mise à jour.
Si une application cliente verrouille une entrée, nous pouvons exécuter le processeur d'entrée dessus à l'aide de la commande IgnoreLock()
méthode. Il ignorera le verrou et accédera à l'entrée pour la traiter.
Avant d'utiliser notre nouveau processeur, nous devons déployer la DLL avec notre processeur et ses dépendances pour NCache. Nous pouvons utiliser le Powershell Install-NCacheModule
applet de commande ou NCache Gestionnaire Web. Pour obtenir des instructions sur le déploiement de notre processeur d'entrée à l'aide du gestionnaire Web, consultez Déployer des fournisseurs.
Par exemple, arrêtons notre instance "demoCache" et exécutons le Powershell Install-NCacheModule
applet de commande,
NCache Détails NCache Processeur d'entrée Implémentation du processeur d'entrée
Comment les processeurs d'entrée traitent-ils comprenant Échecs d'opération ?
Une fois qu'un processeur d'entrée s'exécute, il renvoie une collection de résultats de type IEntryProcessorResult
. Chaque résultat contient un IsSuccessful
drapeau et un Value
avec le résultat de nos modifications. Pour notre processeur d'entrée d'échantillons, le Value
propriété contiendra soit false
, si le client n'a pas d'achat récent, ou un client mis à jour, sinon.
Si une exception est levée pendant l'exécution du processeur d'entrée, le IsSuccessful
le drapeau sera false
et par Exception
La propriété sera renseignée avec l'exception levée.
Pour rendre notre processeur d'entrée à sécurité intégrée, nous devons gérer toutes les exceptions potentielles. Par exemple, nous pourrions obtenir un OperationFailedException
s'il y avait un échec de connexion. De plus, nous pourrions obtenir un
EntryProcessorException
, dans ce cas, le processeur d'entrées n'a modifié aucune entrée de cache.
C'est ainsi que nous pourrions afficher les résultats de saisie et les éventuels messages d'exception,
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}"); } |
Maintenant, exécutons nos trois alternatives côte à côte. Je les ai exécutés sur ma machine avec NCache installé localement et en utilisant 20 clients aléatoires que j'ai générés en utilisant Bogus. Et voilà le résultat,
Conclusion
En définitive, l'alternative avec un processeur d'entrée était la plus rapide. Il s'est terminé en 12 millisecondes, tandis que celui avec les méthodes Bulk s'est terminé en 72 millisecondes. Avec Entry Processors, nous avons constaté une amélioration des performances puisque nous avons évité tous les déplacements réseau excessifs en doublant les points de nos clients directement sur le serveur.
C'est ce que sont les processeurs d'entrée et comment ils fonctionnent. Même si nous n'avons pas écrit de benchmark pour tester cela NCache fonctionnalité, cette comparaison nous donne une idée de la façon d'utiliser les processeurs d'entrée. Avec eux, on économise quelques allers-retours vers nos NCache serveur en traitant nos entrées de cache directement dans un NCache serveur. La prochaine fois que vous devrez mettre à jour certaines de vos entrées de cache, essayez les processeurs d'entrée.
Pour plus de détails sur le fonctionnement des processeurs de saisie, consultez Fonctionnement du processeur d'entrée en cache.
Pour suivre le code, nous avons écrit dans ce post, vérifiez mon NCache Référentiel de démonstration sur GitHub.