Troubleshooting - Amazon ElastiCache for Redis

Troubleshooting

Les éléments suivants doivent être vérifiés lors du dépannage des problèmes de connectivité persistants avec ElastiCache :

Groupes de sécurité

Les groupes de sécurité sont des pare-feu virtuels protégeant votre client ElastiCache (instance EC2, fonction AWS Lambda, conteneur Amazon ECS, etc.) et votre cluster ElastiCache. Les groupes de sécurité sont avec état, ce qui signifie qu'une fois le trafic entrant ou sortant autorisé, les réponses pour ce trafic seront automatiquement autorisées dans le contexte de ce groupe de sécurité spécifique.

La fonction avec état exige que le groupe de sécurité suive constamment toutes les connexions autorisées, et il existe une limite pour les connexions suivies. Si la limite est atteinte, les nouvelles connexions échoueront. Reportez-vous à la section de dépannage pour savoir comment identifier si les limites ont été atteintes du côté du client ou d'Elasticache.

Vous pouvez affecter simultanément un seul groupe de sécurité au cluster client et à ElastiCache, ou des groupes de sécurité individuels pour chacun d'eux.

Dans les deux cas, vous devez autoriser le trafic sortant TCP sur le port ElastiCache à partir de la source et le trafic entrant sur le même port vers ElastiCache. Le port par défaut est 11211 pour Memcached et 6379 pour Redis. Par défaut, les groupes de sécurité autorisent la totalité du trafic sortant. Dans ce cas, seule la règle entrante dans le groupe de sécurité cible est requise.

Pour de plus amples informations, veuillez consulter Modèles d'accès à un cluster ElastiCache dans un Amazon VPC.

Listes ACL réseau

Les listes de contrôle d'accès réseau (ACL) sont des règles sans état. Le trafic doit être autorisé dans les deux sens (entrant et sortant) pour réussir. Les listes d'accès réseau sont affectées à des sous-réseaux et non à des ressources spécifiques. Il est possible d'avoir la même ACL affectée à ElastiCache et à la ressource du client, surtout s'ils se trouvent dans le même sous-réseau.

Par défaut, les listes ACL réseau autorisent tout le trafic. Toutefois, il est possible de les personnaliser pour refuser ou autoriser le trafic. En outre, l'évaluation des règles ACL est séquentielle, ce qui signifie que la règle avec le nombre le plus bas correspondant au trafic l'autorisera ou le refusera. La configuration minimale pour autoriser le trafic Redis est la suivante :

ACL réseau côté client :

  • Règles entrantes :

  • Numéro de règle : de préférence inférieur à toute règle de refus ;

  • Type : Règle TCP personnalisée ;

  • Protocole : TCP

  • Plage de ports : 1024-65535

  • Source : 0.0.0.0/0 (ou créer des règles individuelles pour les sous-réseaux de cluster ElastiCache)

  • Autoriser/Refuser : Autoriser

  • Règles sortantes :

  • Numéro de règle : de préférence inférieur à toute règle de refus ;

  • Type : Règle TCP personnalisée ;

  • Protocole : TCP

  • Plage de ports : 6379

  • Source : 0.0.0.0/0 (ou les sous-réseaux de cluster ElastiCache. Gardez à l'esprit que l'utilisation d'adresses IP spécifiques peut créer des problèmes en cas de basculement ou de mise à l'échelle du cluster)

  • Autoriser/Refuser : Autoriser

ACL réseau ElastiCache :

  • Règles entrantes :

  • Numéro de règle : de préférence inférieur à toute règle de refus ;

  • Type : Règle TCP personnalisée ;

  • Protocole : TCP

  • Plage de ports : 6379

  • Source : 0.0.0.0/0 (ou créer des règles individuelles pour les sous-réseaux de cluster ElastiCache)

  • Autoriser/Refuser : Autoriser

  • Règles sortantes :

  • Numéro de règle : de préférence inférieur à toute règle de refus ;

  • Type : Règle TCP personnalisée ;

  • Protocole : TCP

  • Plage de ports : 1024-65535

  • Source : 0.0.0.0/0 (ou les sous-réseaux de cluster ElastiCache. Gardez à l'esprit que l'utilisation d'adresses IP spécifiques peut créer des problèmes en cas de basculement ou de mise à l'échelle du cluster)

  • Autoriser/Refuser : Autoriser

Pour plus d'informations, veuillez consulter ACL réseau.

Tables de routage

De même que les ACL réseau, chaque sous-réseau peut avoir des tables de routage différentes. Si les clients et le cluster ElastiCache se trouvent dans des sous-réseaux différents, assurez-vous que leurs tables de routage leur permettent de communiquer les uns avec les autres.

Des environnements plus complexes, impliquant plusieurs VPC, un routage dynamique ou des pare-feu réseau, peuvent devenir difficiles à dépanner. Veuillez consulter Validation de connectivité réseau pour confirmer que vos paramètres réseau sont appropriés.

Résolution DNS

ElastiCache fournit les points de terminaison de service basés sur des noms DNS. Les points de terminaison disponibles sont Configuration, Primary, Reader et Node. Pour plus d'informations, voir Recherche de points de terminaison de connexion.

En cas de basculement ou de modification de cluster, l'adresse associée au nom du point de terminaison peut changer et sera automatiquement mise à jour.

Les paramètres DNS personnalisés (c'est-à-dire ne pas utiliser le service DNS VPC) peuvent ne pas connaître les noms DNS fournis par Elasticache. Assurez-vous que votre système peut résoudre avec succès les points de terminaison ElastiCache à l'aide d'outils système tels que dig (comme indiqué ci-dessous) ou nslookup.

$ dig +short example.xxxxxx.ng.0001.use1.cache.amazonaws.com example-001.xxxxxx.0001.use1.cache.amazonaws.com. 1.2.3.4

Vous pouvez également forcer la résolution de noms via le service DNS VPC :

$ dig +short example.xxxxxx.ng.0001.use1.cache.amazonaws.com @169.254.169.253 example-001.tihewd.0001.use1.cache.amazonaws.com. 1.2.3.4

Identification des problèmes liés aux diagnostics côté serveur

Les métriques CloudWatch et les informations d'exécution du moteur ElastiCache sont des sources ou des informations courantes permettant d'identifier les sources potentielles de problèmes de connexion. Une bonne analyse commence généralement par les éléments suivants :

  • Utilisation du processeur : Redis est une application multithread. Cependant, l'exécution de chaque commande se produit dans un seul thread (principal). Pour cette raison, ElastiCache fournit les métriques CPUUtilization et EngineCPUUtilization. EngineCPUUtilization fournit l'utilisation de l'UC dédiée au processus Redis, et CPUUtilization l'utilisation sur tous les vCPU. Les nœuds avec plus d'un vCPU ont généralement des valeurs différentes pour CPUUtilization et EngineCPUUtilization, le second étant généralement plus élevé. Une EngineCPUUtilization élevée peut être causée par un nombre élevé de requêtes ou d'opérations complexes qui prennent beaucoup de temps d'UC à finaliser. Vous pouvez identifier les deux avec les éléments suivants :

    • Nombre élevé de demandes : recherchez des augmentations sur d'autres métriques correspondant au modèle EngineCPUUtilization. Les métriques utiles sont les suivantes :

      • CacheHits et CacheMisses : le nombre de demandes réussies ou de demandes qui n'ont pas trouvé d'élément valide dans le cache. Si le ratio des manquements par rapport aux résultats est élevé, l'application perd du temps et des ressources avec des demandes infructueuses.

      • SetTypeCmds et GetTypeCmds : ces métriques en corrélation avec EngineCPUUtilization peuvent aider à comprendre si la charge est significativement plus élevée pour les demandes d'écriture, mesurées par SetTypeCmds, ou les lectures, mesurées par GetTypeCmds. Si la charge est principalement composée de lectures, l'utilisation de plusieurs réplicas en lecture peut équilibrer les demandes sur plusieurs nœuds et épargner le principal pour les écritures. Dans les clusters désactivés en mode cluster, l'utilisation de réplicas en lecture peut être effectuée en créant une configuration de connexion supplémentaire dans l'application à l'aide du point de terminaison du lecteur ElastiCache. Pour plus d'informations, voir Recherche de points de terminaison de connexion. Les opérations de lecture doivent être soumises à cette connexion supplémentaire. Les opérations d'écriture seront effectuées via le point de terminaison principal normal. En mode cluster activé, il est conseillé d'utiliser une bibliothèque qui prend en charge les réplicas en lecture de façon native. Avec les bons indicateurs, la bibliothèque sera en mesure de découvrir automatiquement la topologie du cluster, les nœuds de réplica, d'activer les opérations de lecture via la commande Redis READONLY et de soumettre les demandes de lecture aux réplicas.

    • Nombre élevé de connexions :

      • CurrConnections et NewConnections : CurrConnection est le nombre de connexions établies au moment de la collectie de données, tandis queNewConnections indique le nombre de connexions créées au cours de la période.

        La création et la gestion des connexions impliquent une surcharge d'UC importante. En outre, la connexion en trois temps TCP requise pour créer des connexions affectera négativement les temps de réponse globaux.

        Un nœud ElastiCache avec des milliers de NewConnections par minute indique qu'une connexion est créée et utilisée par quelques commandes, ce qui n'est pas optimal. Le fait de maintenir les connexions établies et de les réutiliser pour de nouvelles opérations est une bonne pratique. Ceci est possible lorsque l'application client prend en charge et implémente correctement le regroupement de connexions ou les connexions persistantes. Avec le regroupement de connexions, le nombre de currConnections n'a pas de grandes variations et les NewConnections doivent être aussi faibles que possible. Redis offre des performances optimales avec un petit nombre de currConnections. En maintenant currConnection dans l'ordre de dizaines ou de centaines, on minimise l'utilisation des ressources nécessaires à la prise en charge des connexions individuelles, comme les tampons client et les cycles d'UC pour servir la connexion.

    • Débit réseau :

      • Déterminer la bande passante : les nœuds ElastiCache ont une bande passante réseau proportionnelle à la taille du nœud. Comme les applications ont des caractéristiques différentes, les résultats peuvent varier en fonction de la charge de travail. Par exemple, les applications avec un nombre élevé de petites demandes ont tendance à affecter davantage l'utilisation de l'UC que le débit réseau, tandis que les clés plus grandes provoqueront une utilisation plus élevée du réseau. Pour cette raison, il est conseillé de tester les nœuds avec la charge de travail réelle pour une meilleure compréhension des limites.

        La simulation de la charge à partir de l'application donnerait des résultats plus précis. Cependant, les outils de référence peuvent donner une bonne idée des limites.

      • Dans les cas où les requêtes sont principalement des lectures, l'utilisation de réplicas pour les opérations de lecture allégera la charge sur le nœud primaire. Si le cas d'utilisation est principalement des écritures, l'utilisation de nombreux réplicas amplifiera l'utilisation du réseau. Pour chaque octet écrit sur le nœud primaire, N octets seront envoyés aux réplicas, N étant le nombre de réplicas. La bonne pratique pour les charges de travail intensives en écriture consiste à utiliser ElastiCache for Redis avec le mode cluster activé afin que les écritures puissent être équilibrées sur plusieurs partitions, ou à augmenter un type de nœud avec davantage de capacités réseau.

      • Les métriques CloudwatchMetrics NetworkBytesIn et NetworkBytesOut fournissent respectivement la quantité de données entrant ou sortant du nœud. ReplicationBytes est le trafic dédié à la réplication des données.

      Pour plus d’informations, consultez Limites liées au réseau.

    • Commandes complexes : les commandes Redis sont servies sur un seul thread, ce qui signifie que les demandes sont servies de façon séquentielle. Une seule commande lente peut affecter d'autres demandes et connexions, aboutissant ainsi à des délais d'expiration. L'utilisation de commandes qui agissent sur plusieurs valeurs, clés ou types de données doit être effectuée avec soin. Les connexions peuvent être bloquées ou interrompues en fonction du nombre de paramètres ou de la taille de ses valeurs d'entrée ou de sortie.

      Un exemple bien connu est la commande KEYS. Il balaie le keyspace entier en recherchant un modèle donné et bloque l'exécution d'autres commandes lors de son exécution. Redis utilise la notation « Big O » pour décrire la complexité de ses commandes.

      La commande de clés a une complexité temporelle O(N), N étant le nombre de clés dans la base de données. Par conséquent, plus le nombre de clés est grand, plus la commande sera lente. KEYS peut causer des problèmes de différentes manières : si aucun modèle de recherche n'est utilisé, la commande retournera tous les noms de clés disponibles. Dans les bases de données contenant des milliers ou des millions d'éléments, une sortie énorme sera créée et inondera les tampons réseau.

      Si un modèle de recherche est utilisé, seules les clés correspondant au modèle seront retournées au client. Cependant, le moteur balaie toujours le keyspace entier pour le rechercher, et le temps nécessaire pour finaliser la commande sera le même.

      Une alternative pour KEYS est la commande SCAN. Elle itère sur le keyspace et limite les itérations dans un nombre spécifique d'éléments, en évitant les blocs prolongés sur le moteur.

      L'analyse dispose du paramètre COUNT, utilisé pour définir la taille des blocs d'itération. La valeur par défaut est de 10 (10 éléments par itération).

      Selon le nombre d'éléments dans la base de données, les petits blocs de valeur COUNT nécessitent plus d'itérations pour effectuer une analyse complète, tandis que des valeurs plus grandes garderont le moteur occupé plus longtemps à chaque itération. Alors que les petites valeurs de nombre ralentiront SCAN sur les grandes bases de données, des valeurs plus grandes peuvent causer les mêmes problèmes que ceux mentionnés pour KEYS.

      À titre d'exemple, l'exécution de la commande SCAN avec la valeur de nombre 10 nécessite 100 000 répétitions sur une base de données avec 1 million de clés. Si le temps de transmission aller-retour moyen du réseau est de 0,5 milliseconde, environ 50 000 millisecondes (50 secondes) seront consacrées au transfert de demandes.

      D'autre part, si la valeur de comptage était de 100 000, une seule itération serait nécessaire et seulement 0,5 ms serait dépensé pour le transférer. Cependant, le moteur serait complètement bloqué pour d'autres opérations jusqu'à ce que la commande ait fini de balayer tout le keyspace.

      En outre KEYS, plusieurs autres commandes sont potentiellement nuisibles si elles ne sont pas utilisées correctement. Pour afficher la liste de toutes les commandes et leur complexité temporelle respective, accédez à https://redis.io/commands.

      Exemples de problèmes potentiels :

      • Scripts Lua : Redis fournit un interpréteur Lua intégré, permettant l'exécution de scripts côté serveur. Les scripts Lua sur Redis sont exécutés au niveau du moteur et sont atomiques par définition, ce qui signifie qu'aucune autre commande ou aucun autre script ne sera autorisé à s'exécuter pendant qu'un script est en cours d'exécution. Les scripts Lua offrent la possibilité d'exécuter plusieurs commandes, algorithmes de prise de décision, analyse de données, et autres directement sur le moteur Redis. Alors que l'atomicité des scripts et les chances de décharger l'application sont tentantes, les scripts doivent être utilisés avec prudence et pour de petites opérations. Sur ElastiCache, le temps d'exécution des scripts Lua est limité à 5 secondes. Les scripts qui n'ont pas été écrits dans le keyspace seront automatiquement résiliés après la période de 5 secondes. Pour éviter la corruption des données et les incohérences, le nœud basculera si l'exécution du script n'a pas été terminée en 5 secondes et a eu une écriture pendant son exécution. Les transactions sont l'alternative pour garantir la cohérence de plusieurs modifications de clés associées dans Redis. Une transaction permet l'exécution d'un bloc de commandes, en surveillant les clés existantes pour les modifications. Si l'une des clés surveillées change avant la fin de la transaction, toutes les modifications sont supprimées.

      • Suppression en masse d'éléments : la commande DEL accepte plusieurs paramètres, qui sont les noms de clés à supprimer. Les opérations de suppression sont synchrones et prennent beaucoup de temps d'UC si la liste des paramètres est volumineuse ou contient une liste, un ensemble, un ensemble trié ou un hachage de grande taille (structures de données contenant plusieurs sous-éléments). En d'autres termes, même la suppression d'une seule clé peut prendre beaucoup de temps si elle comporte de nombreux éléments. L'alternative à DEL estUNLINK, qui est une commande asynchrone disponible depuis Redis 4. UNLINK doit avoir la préférence sur DEL dès que possible. À partir d'ElastiCache for Redis 6x, le paramètre lazyfree-lazy-user-del fait en sorte que la commande DEL se comporte comme UNLINK lorsqu'il est activé. Pour plus d’informations, consultez la rubrique Modifications des paramètres Redis 6.0.

      • Commandes agissant sur plusieurs clés : DEL a été mentionné précédemment comme une commande qui accepte plusieurs arguments et son temps d'exécution sera directement proportionnel à cela. Cependant, Redis fournit beaucoup plus de commandes qui fonctionnent de la même manière. À titre d'exemple, MSET et MGET permettent l'insertion ou la récupération de plusieurs clés de chaîne à la fois. Leur utilisation peut être bénéfique pour réduire la latence réseau inhérente à plusieurs commandes SET ou GET. Cependant, une liste exhaustive de paramètres affectera l'utilisation de l'UC.

        Bien que l'utilisation de l'UC seule ne soit pas la cause des problèmes de connectivité, passer trop de temps pour traiter une seule ou quelques commandes sur plusieurs clés peut provoquer l'échec d'autres demandes et augmenter l'utilisation globale de l'UC.

        Le nombre de clés et leur taille affecteront la complexité de la commande et, par conséquent, le temps d'exécution.

        Autres exemples de commandes qui peuvent agir sur plusieurs clés : HMGET, HMSET, MSETNX, PFCOUNT, PFMERGE, SDIFF, SDIFFSTORE, SINTER, SINTERSTORE, SUNION, SUNIONSTORE, TOUCH, ZDIFF, ZDIFFSTORE, ZINTER ou ZINTERSTORE.

      • Commandes agissant sur plusieurs types de données : Redis fournit également des commandes qui agissent sur une ou plusieurs clés, quel que soit leur type de données. ElastiCache for Redis fournit la métrique KeyBasedCmds pour surveiller ces commandes. Cette métrique additionne l'exécution des commandes suivantes dans la période sélectionnée :

        • Complexité O(N) :

          • KEYS

        • O(1)

          • EXISTS

          • OBJECT

          • PTTL

          • RANDOMKEY

          • TTL

          • TYPE

          • EXPIRE

          • EXPIREAT

          • MOVE

          • PERSIST

          • PEXPIRE

          • PEXPIREAT

          • UNLINK (O(N) pour récupérer de la mémoire. Cependant, la tâche de récupération de mémoire se produit dans un thread séparé et ne bloque pas le moteur

        • Différents temps de complexité en fonction du type de données :

          • DEL

          • DUMP

          • RENAME est considéré comme une commande avec une complexité O(1), mais exécute DEL en interne. Le temps d'exécution varie en fonction de la taille de la clé renommée.

          • RENAMENX

          • RESTORE

          • SORT

        • Gros hachages : le hachage est un type de données qui autorise une seule clé avec plusieurs sous-éléments clé-valeur. Chaque hachage peut stocker 4 294 967 295 éléments et les opérations sur de gros hachages peuvent devenir coûteuses. De même que pour KEYS, les hachages ont la commande HKEYS avec une complexité temporelle O(N), N étant le nombre d'éléments dans le hachage. HSCAN doit avoir la préférence sur HKEYS pour éviter les commandes à exécution longue. HDEL, HGETALL, HMGET, HMSET et HVALS sont des commandes qui doivent être utilisées avec prudence sur les gros hachages.

      • Autres structures big data : outre les hachages, d'autres structures de données peuvent être intensives en UC. Les ensembles, les listes, les ensembles triés et les Hyperloglogs peuvent également prendre beaucoup de temps à être manipulés en fonction de leur taille et des commandes utilisées. Pour plus d'informations sur ces commandes, veuillez consulter https://redis.io/commands.

Validation de connectivité réseau

Après avoir examiné les configurations réseau liées à la résolution DNS, aux groupes de sécurité, aux listes ACL réseau et aux tables de routage, la connectivité peut être validée à l'aide de VPC Reachability Analyzer et des outils système.

Reachability Analyzer testera la connectivité réseau et confirmera que toutes les exigences et autorisations sont satisfaites. Pour les tests ci-dessous, vous aurez besoin de l'ID ENI (Identification d'interface réseau Elastic) de l'un des nœuds ElastiCache disponibles dans votre VPC. Vous pouvez le trouver en procédant comme suit :

  1. Accédez à https://console.aws.amazon.com/ec2/v2/home?#NIC :

  2. Filtrez la liste d'interface en fonction du nom de votre cluster Elasticache ou de l'adresse IP obtenue par le biais des validations DNS précédemment.

  3. Notez ou enregistrez l'ID ENI. Si plusieurs interfaces sont affichées, vérifiez la description pour confirmer qu'elles appartiennent au cluster ElastiCache approprié et choisissez l'une d'entre elles.

  4. Passez à l'étape suivante.

  5. Créez un chemin d'analyse sur https://console.aws.amazon.com/vpc/home?#ReachabilityAnalyzer et choisissez les options suivantes :

    • Type de source : choisissez Instance si votre client ElastiCache s'exécute sur une instance Amazon EC2 ou Network Interface (Interface réseau) s'il utilise un autre service, comme AWS FargateAmazon ECS avec réseau awsvpc, AWS Lambda, etc.), et l'ID de ressource respectif (instance EC2 ou ID ENI) ;

    • Type de destination : choisissez Network Interface (Interface réseau) et sélectionnez l'ENI Elasticache dans la liste.

    • Port de destination : spécifiez 6379 pour ElastiCache for Redis ou 11211 pour ElastiCache for Memcached. Ce sont les ports définis avec la configuration par défaut et cet exemple suppose qu'ils ne sont pas modifiés.

    • Protocole : TCP

Créez le chemin d'analyse et attendez le résultat quelques instants. Si le statut n'est pas accessible, ouvrez les détails de l'analyse et veuillez consulter l'explorateur d'analyse pour plus de détails sur les cas où les demandes ont été bloquées

Si les tests d'accessibilité aboutissent, passez à la vérification au niveau du système d'exploitation.

Pour valider la connectivité TCP sur le port de service ElastiCache : sur Amazon Linux, Nping est disponible dans le package nmap et peut tester la connectivité TCP sur le port ElastiCache, ainsi que fournir le temps de transmission aller-retour réseau pour établir la connexion. Utilisez cette option pour valider la connectivité réseau et la latence actuelle sur le cluster ElastiCache, comme indiqué ci-dessous :

$ sudo nping --tcp -p 6379 example.xxxxxx.ng.0001.use1.cache.amazonaws.com Starting Nping 0.6.40 ( http://nmap.org/nping ) at 2020-12-30 16:48 UTC SENT (0.0495s) TCP ... (Output suppressed ) Max rtt: 0.937ms | Min rtt: 0.318ms | Avg rtt: 0.449ms Raw packets sent: 5 (200B) | Rcvd: 5 (220B) | Lost: 0 (0.00%) Nping done: 1 IP address pinged in 4.08 seconds

Par défaut, nping envoie 5 sondes avec un délai de 1 seconde entre elles. Vous pouvez utiliser l'option « -c » pour augmenter le nombre de sondes et « --delay » pour modifier la durée avant l'envoi d'un nouveau test.

Si les tests avec nping échouent et si les tests VPC Reachability Analyzer aboutissent, demandez à votre administrateur système d'examiner les règles de pare-feu basées sur l'hôte, les règles de routage asymétrique ou toute autre restriction possible au niveau du système d'exploitation.

Sur la console ElastiCache, vérifiez si l'option Encryption in-transit (Chiffrement en transit) est activée dans les détails de votre cluster ElastiCache. Si le chiffrement en transit est activé, vérifiez si la session TLS peut être établie à l'aide de la commande suivante :

openssl s_client -connect example.xxxxxx.use1.cache.amazonaws.com:6379

Une sortie étendue est attendue si la connexion et la négociation TLS aboutissent. Vérifiez le code de retour disponible sur la dernière ligne, la valeur doit être 0 (ok). Si openssl renvoie quelque chose de différent, vérifiez la raison de l'erreur sur https://www.openssl.org/docs/man1.0.2/man1/verify.html#DIAGNOSTICS.

Si tous les tests d'infrastructure et de système d'exploitation aboutissent, mais que votre application ne peut toujours pas se connecter à ElastiCache, vérifiez si les configurations de l'application sont conformes aux paramètres ElastiCache. Les erreurs les plus courantes sont les suivantes :

  • Votre application ne prend pas en charge le mode cluster ElastiCache et ElastiCache a activé le mode cluster ;

  • Votre application ne prend pas en charge TLS/SSL et ElastiCache a activé le chiffrement en transit ;

  • L'application prend en charge TLS/SSL, mais ne possède pas les bons indicateurs de configuration ou les autorités de certification fiables ;

Limites liées au réseau

  • Nombre maximal de connexions : il existe des limites strictes pour les connexions simultanées. Chaque nœud ElastiCache permet jusqu'à 65 000 connexions simultanées sur tous les clients. Cette limite peut être surveillée via les métriques CurrConnections sur CloudWatch. Cependant, les clients ont également leurs limites pour les connexions sortantes. Sous Linux, vérifiez la plage de ports éphémères autorisée à l'aide de la commande :

    # sysctl net.ipv4.ip_local_port_range net.ipv4.ip_local_port_range = 32768 60999

    Dans l'exemple précédent, 28 231 connexions seront autorisées à partir de la même source, vers la même adresse IP de destination (nœud ElastiCache) et le même port. La commande suivante indique le nombre de connexions existant pour un nœud Elasticache spécifique (IP 1.2.3.4) :

    ss --numeric --tcp state connected "dst 1.2.3.4 and dport == 6379" | grep -vE '^State' | wc -l

    Si le nombre est trop élevé, votre système peut devenir surchargé en essayant de traiter les demandes de connexion. Il est conseillé d'envisager d'implémenter des techniques telles que le regroupement de connexions ou les connexions persistantes pour mieux gérer les connexions. Dans la mesure du possible, configurez le groupe de connexions pour limiter le nombre maximal de connexions à quelques centaines. En outre, une logique d'interruptions exponentielles pour gérer les expirations de délai d'attente ou d'autres exceptions de connexion serait souhaitable pour éviter l'abandon de connexion en cas de problème.

  • Limites de trafic réseau : vérifiez les éléments métriques CloudWatch for Redis suivantes pour identifier les limites réseau possibles atteintes sur le nœud ElastiCache :

    • NetworkBandwidthInAllowanceExceeded / NetworkBandwidthOutAllowanceExceeded : paquets réseau formés parce que le débit dépassait la limite de bande passante agrégée.

      Il est important de noter que chaque octet écrit sur le nœud primaire sera répliqué sur N réplicas, N étant le nombre de réplicas. Les clusters avec de petits types de nœuds, plusieurs réplicas et des demandes d'écriture intensives peuvent ne pas être en mesure de faire face à l'arriéré de réplication. Dans de tels cas, la bonne pratique consiste à effectuer une augmentation d'échelle (changer le type de nœud), une évolutivité horizontale (ajouter des partitions dans des clusters activés en mode cluster), de réduire le nombre de réplicas ou de réduire le nombre d'écritures.

    • NetworkConntrackAllowanceExceeded : paquets formés, car le nombre maximal de connexions suivies dans tous les groupes de sécurité affectés au nœud a été dépassé. Les nouvelles connexions échoueront probablement pendant cette période.

    • NetworkPackets PerSecondAllowanceExceeded : nombre maximal de paquets par seconde dépassé. Les charges de travail basées sur un taux élevé de très petites demandes peuvent atteindre cette limite avant la bande passante maximale.

    Les mesures ci-dessus sont le moyen idéal de confirmer que les nœuds atteignent leurs limites réseau. Cependant, les limites sont également identifiables par des plateaux sur les métriques du réseau.

    Si les plateaux sont observés pendant des périodes prolongées, ils seront probablement suivis d'un retard de réplication, d'une augmentation des octets utilisés pour le cache, d'une chute de la mémoire libérable, d'une hausse des échanges et de l'utilisation de l'UC. Les instances Amazon EC2 ont également des limites réseau qui peuvent être suivies via des métriques de pilote ENA. Les instances Linux avec prise en charge réseaux améliorée et les pilotes ENA version 2.2.10 ou plus récente peuvent consulter les compteurs de limite avec la commande suivante :

    # ethtool -S eth0 | grep "allowance_exceeded"

Utilisation de l'UC

La métrique d'utilisation du processeur est le point de départ de l'enquête, et les éléments suivants peuvent aider à réduire les problèmes possibles du côté d'ElastiCache :

  • Redis SlowLogs : la configuration par défaut d'ElastiCache conserve les 128 dernières commandes qui ont pris plus de 10 millisecondes pour s'effectuer. L'historique des commandes lentes est conservé pendant l'exécution du moteur et sera perdu en cas d'échec ou de redémarrage. Si la liste atteint 128 entrées, les anciens événements seront supprimés pour faire de la place aux nouveaux. La taille de la liste des événements lents et le temps d'exécution considéré comme lent peuvent être modifiés via les paramètres slowlog-max-len et slowlog-log-slower-than dans un groupe de paramètres personnalisé. La liste des journaux lents peut être récupérée en exécutant SLOWLOG GET 128 sur le moteur, 128 étant les 128 dernières commandes lentes signalées. Chaque entrée contient les champs suivants :

    1) 1) (integer) 1 -----------> Sequential ID 2) (integer) 1609010767 --> Timestamp (Unix epoch time)of the Event 3) (integer) 4823378 -----> Time in microseconds to complete the command. 4) 1) "keys" -------------> Command 2) "*" ----------------> Arguments 5) "1.2.3.4:57004"-> Source

    L'événement ci-dessus s'est produit le 26 décembre à 19:26:07 UTC, a pris 4,8 secondes (4 823 ms) et a été causé par la commande KEYS demandée auprès du client 1.2.3.4.

    Sous Linux, l'horodatage peut être converti avec la date de commande :

    $ date --date='@1609010767' Sat Dec 26 19:26:07 UTC 2020

    Avec Python :

    >>> from datetime import datetime >>> datetime.fromtimestamp(1609010767) datetime.datetime(2020, 12, 26, 19, 26, 7)

    Ou sous Windows avec PowerShell :

    PS D:\Users\user> [datetimeoffset]::FromUnixTimeSeconds('1609010767') DateTime : 12/26/2020 7:26:07 PM UtcDateTime : 12/26/2020 7:26:07 PM LocalDateTime : 12/26/2020 2:26:07 PM Date : 12/26/2020 12:00:00 AM Day : 26 DayOfWeek : Saturday DayOfYear : 361 Hour : 19 Millisecond : 0 Minute : 26 Month : 12 Offset : 00:00:00Ticks : 637446075670000000 UtcTicks : 637446075670000000 TimeOfDay : 19:26:07 Year : 2020

    Beaucoup de commandes lentes dans un court laps de temps (même minute ou moins) sont une source de préoccupation. Examinez la nature des commandes et la façon dont elles peuvent être optimisées (voir les exemples précédents). Si des commandes avec une complexité temporelle O(1) sont fréquemment signalées, vérifiez les autres facteurs d'utilisation élevée de l'UC mentionnés précédemment.

  • Métriques de latence : ElastiCache for Redis fournit des métriques CloudWatch pour surveiller la latence moyenne pour différentes classes de commandes. Le point de données est calculé en divisant le nombre total d'exécutions de commandes dans la catégorie par le temps total d'exécution de la période. Il est important de comprendre que les résultats des métriques de latence sont un agrégat de commandes multiples. Une seule commande peut entraîner des résultats inattendus, tels que des délais d'expiration, sans impact significatif sur les métriques. Dans de tels cas, les événements de journaux lents constitueraient une source d'information plus précise. La liste suivante contient les métriques de latence disponibles et les commandes correspondantes qui les affectent.

    • EvalBasedCmdSlatency : lié aux commandes de script Lua, eval, evalsha ;

    • GeoSpatialBasedCmdsLatency : geodist, geohash, geopos, georadius, georadiusbymember, geoadd ;

    • GetTypeCmdsLatency : commandes de lecture, quel que soit le type de données ;

    • HashBasedCmdsLatency : hexists, hget, hgetall, hkeys, hlen, hmget, hvals, hstrlen, hdel, hincrby, hincrbyfloat, hmset, hset, hsetnx ;

    • HyperLogLogBasedCmdsLatency : pfselftest, pfcount, pfdebug, pfadd, pfmerge ;

    • KeyBasedCmdSlatency : commandes qui peuvent agir sur différents types de données : dump, exists, keys, object, pttl, randomkey, ttl, type, del, expire, expireat, move, persist, pexpire, pexpireat, rename, renamenx, restoreK, sort, unlink ;

    • ListBasedCmdSlatence : lindex, llen, lrange, blpop, brpop, brpoplpush, linsert, lpop, lpush, lpushx, lrem, lset, ltrim, rpop, rpoplpush, rpushx ;

    • PubSubBasedCmdsLatency : psubscribe, publish, pubsub, punsubscribe, subscribe, unsubscribe;

    • SetBasedCmdsLatency : scard, sdiff, sinter, sismember, smembers, srandmember, sunion, sadd, sdiffstore, sinterstore, smove, spop, srem, sunionstore ;

    • SetTypeCmdsLatency : commandes d'écriture, quel que soit le type de données ;

    • SortedSetBasedCmdsLatency : zcard, zcount, zrange, zrangebyscore, zrank, zrevrange, zrevrangebyscore, zrevrank, zscore, zrangebylex, zrevrangebylex, zlexcount, zadd. zincrby, zinterstore, zrem, zremrangebyrank, zremrangebyscore, zunionstore, zremrangebylex, zpopmax, zpopmin, bzpopmin, bzpopmax ;

    • StringBasedCmdsLatency : bitcount, get, getbit, getrange, mget, strlen, substr, bitpos, append, bitop, bitfield, decr, decrby, getset, incr, incrby, incrbyfloat, mset, msetnx, psetex, set, setbit, setex, setnx, setrange ;

    • StreamBasedCmdsLatency : xrange, xrevrange, xlen, xread, xpending, xinfo, xadd, xgroup, readgroup, xack, xclaim, xdel, xtrim, xsetid ;

  • Commandes d'exécution Redis :

    • info commandstats : fournit une liste des commandes exécutées depuis le démarrage du moteur Redis, leur nombre d'exécutions cumulées, leur temps d'exécution total et leur temps d'exécution moyen par commande ;

    • client list : fournit une liste des clients actuellement connectés et des informations pertinentes comme l'utilisation des tampons, la dernière commande exécutée, etc.

  • Backup and replication : les versions d'ElastiCache for Redis antérieures à la version 2.8.22 utilisent un processus avec une fonction fork pour créer des sauvegardes et traiter les synchronisations complètes avec les réplicas. Cette méthode peut entraîner une surcharge de mémoire importante pour les cas d'utilisation intensifs en écriture.

    À partir d'Elasticache Redis 2.8.22, AWS introduit une méthode de sauvegarde et de réplication sans fonction fork. La nouvelle méthode peut retarder les écritures afin d'éviter les échecs. Les deux méthodes peuvent provoquer des périodes d'utilisation de l'UC plus élevée, conduire à des temps de réponse plus élevés et, par conséquent, conduire à des délais d'attente du client pendant leur exécution. Vérifiez toujours si les échecs du client se produisent pendant la fenêtre de sauvegarde ou si la métrique SaveInProgress était de 1 au cours de la période. Il est conseillé de planifier la fenêtre de sauvegarde pour les périodes de faible utilisation afin de minimiser les risques de problèmes avec les clients ou d'échecs de sauvegarde.

Connexions résiliées côté serveur

La configuration d'ElastiCache for Redis par défaut maintient les connexions client établies indéfiniment. Toutefois, dans certains cas, la résiliation de la connexion peut être souhaitable. Par exemple :

  • Les bogues dans l'application client peuvent entraîner l'oubli de connexions et leur maintien avec un état inactif. C'est ce que l'on appelle une « fuite de connexion » et sa conséquence est une augmentation constante du nombre de connexions établies observées sur les métriques CurrConnections. Ce comportement peut entraîner une saturation côté client ou côté ElastiCache. Lorsqu'un correctif immédiat n'est pas possible du côté client, certains administrateurs définissent une valeur de « délai d'expiration » dans leur groupe de paramètres ElastiCache. Le délai d'expiration est le temps, en secondes, autorisé pour que les connexions inactives persistent. Si le client n'envoie aucune demande au cours de la période, le moteur Redis résilie la connexion dès que la connexion atteint la valeur de délai d'expiration. De petites valeurs de délai d'expiration peuvent entraîner des déconnexions inutiles et les clients devront les gérer correctement et se reconnecter, ce qui entraîne des retards.

  • La mémoire utilisée pour stocker les clés est partagée avec les tampons client. Les clients lents avec des demandes ou des réponses importantes peuvent exiger une quantité importante de mémoire pour gérer ses tampons. La configuration ElastiCache par défaut pour Redis ne limite pas la taille des tampons de sortie client standard. Si la limite maxmemory est atteinte, le moteur essaiera d'expulser les éléments pour remplir l'utilisation de la mémoire tampon. Dans des conditions de mémoire extrêmement faibles, ElastiCache for Redis peut choisir de déconnecter les clients qui consomment des tampons de sortie client volumineux afin de libérer de la mémoire et de conserver l'intégrité du cluster.

    Il est possible de limiter la taille des tampons client avec des configurations personnalisées et les clients atteignant la limite seront déconnectés. Cependant, les clients devraient être en mesure de gérer des déconnexions inattendues. Les paramètres permettant de gérer la taille des tampons pour les clients réguliers sont les suivants :

    • client-query-buffer-limit : taille maximale d'une seule demande d'entrée ;

    • client-output-buffer-limit-normal-soft-limit : limite logicielle pour les connexions client. La connexion sera interrompue si elle reste au-dessus de la limite logicielle plus longtemps que la durée en secondes définie sur client-output-buffer-limit-normal-soft-seconds ou si elle atteint la limite matérielle ;

    • client-output-buffer-limit-normal-soft-seconds : temps autorisé pour les connexions dépassant la limite client-output-buffer-limit-normal-soft-limit ;

    • client-output-buffer-limit-normal-hard-limit : une connexion atteignant cette limite sera immédiatement résiliée.

    Outre les tampons client habituels, les options suivantes contrôlent le tampon pour les nœuds de réplica et les clients Pub/Sub (Publish/Subscribe) :

    • client-output-buffer-limit-replica-hard-limit;

    • client-output-buffer-limit-replica-soft-seconds;

    • client-output-buffer-limit-replica-hard-limit;

    • client-output-buffer-limit-pubsub-soft-limit;

    • client-output-buffer-limit-pubsub-soft-seconds;

    • client-output-buffer-limit-pubsub-hard-limit;

Dépannage côté client pour les instances Amazon EC2

La charge et la réactivité côté client peuvent également affecter les demandes à ElastiCache. Les limites des instances EC2 et du système d'exploitation doivent être examinées attentivement lors du dépannage des problèmes intermittents de connectivité ou de délai d'expiration. Quelques points clés à observer :

  • UC :

    • Utilisation de l'UC de l'instance EC2 : assurez-vous que l'UC n'a pas été saturée ou proche de 100 %. L'analyse historique peut être effectuée via CloudWatch, mais gardez à l'esprit que la granularité des points de données est de 1 minute (avec la surveillance détaillée activée) ou de 5 minutes ;

    • Si vous utilisez des instances EC2 à capacité extensible, assurez-vous que leur solde de crédit d'UC n'a pas été épuisé. Ces informations sont disponibles sur la métrique CloudWatch CPUCreditBalance,

    • De courtes périodes d'utilisation élevée de l'UC peuvent provoquer des délais d'expiration sans réfléchir à l'utilisation de 100 % sur CloudWatch. De tels cas nécessitent une surveillance en temps réel avec des outils de système d'exploitation tels que top, ps et mpstat.

  • Réseau

    • Vérifiez si le débit réseau est inférieur à des valeurs acceptables en fonction des capacités de l'instance. Pour plus d’informations, consultez la rubrique Types d’instance Amazon EC2.

    • Sur les instances avec le pilote réseau amélioré ena, cochez la case ena statistics (statistiques ena) pour les délais d'expiration ou les limites dépassés. Les statistiques suivantes sont utiles pour confirmer la saturation des limites réseau :

      • bw_in_allowance_exceeded / bw_out_allowance_exceeded : nombre de paquets formés en raison d'un débit entrant ou sortant excessif ;

      • conntrack_allowance_exceeded : nombre de paquets abandonnés en raison de limites de suivi de connexion des groupes de sécurité. Les nouvelles connexions échouent lorsque cette limite est saturée ;

      • linklocal_allowance_exceeded : nombre de paquets abandonnés en raison de requêtes excessives vers des métadonnées d'instance, NTP via VPC DNS. La limite est de 1 024 paquets par seconde pour tous les services ;

      • pps_allowance_exceeded : nombre de paquets abandonnés en raison d'un rapport excessif de paquets par seconde. La limite PPS peut être atteinte lorsque le trafic réseau se compose de milliers ou de millions de très petites demandes par seconde. Le trafic ElastiCache peut être optimisé pour mieux utiliser les paquets réseau via des pipelines ou des commandes qui effectuent plusieurs opérations à la fois comme MGET au lieu de GET.

Disséquer le temps nécessaire pour compléter une seule demande

  • Sur le réseau : Tcpdump et Wireshark (tshark sur la ligne de commande) sont des outils pratiques pour comprendre combien de temps la demande a pris pour parcourir le réseau, atteindre le moteur ElastiCache et obtenir un retour. L'exemple suivant met en évidence une demande unique créée à l'aide de la commande suivante :

    $ echo ping | nc example.xxxxxx.ng.0001.use1.cache.amazonaws.com 6379 +PONG

    Parallèlement à la commande ci-dessus, tcpdump était en exécution et retourné :

    $ sudo tcpdump -i any -nn port 6379 -tt tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 1609428918.917869 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [S], seq 177032944, win 26883, options [mss 8961,sackOK,TS val 27819440 ecr 0,nop,wscale 7], length 0 1609428918.918071 IP 172.31.11.247.6379 > 172.31.11.142.40966: Flags [S.], seq 53962565, ack 177032945, win 28960, options [mss 1460,sackOK,TS val 3788576332 ecr 27819440,nop,wscale 7], length 0 1609428918.918091 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [.], ack 1, win 211, options [nop,nop,TS val 27819440 ecr 3788576332], length 0 1609428918.918122 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [P.], seq 1:6, ack 1, win 211, options [nop,nop,TS val 27819440 ecr 3788576332], length 5: RESP "ping" 1609428918.918132 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [F.], seq 6, ack 1, win 211, options [nop,nop,TS val 27819440 ecr 3788576332], length 0 1609428918.918240 IP 172.31.11.247.6379 > 172.31.11.142.40966: Flags [.], ack 6, win 227, options [nop,nop,TS val 3788576332 ecr 27819440], length 0 1609428918.918295 IP 172.31.11.247.6379 > 172.31.11.142.40966: Flags [P.], seq 1:8, ack 7, win 227, options [nop,nop,TS val 3788576332 ecr 27819440], length 7: RESP "PONG" 1609428918.918300 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [.], ack 8, win 211, options [nop,nop,TS val 27819441 ecr 3788576332], length 0 1609428918.918302 IP 172.31.11.247.6379 > 172.31.11.142.40966: Flags [F.], seq 8, ack 7, win 227, options [nop,nop,TS val 3788576332 ecr 27819440], length 0 1609428918.918307 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [.], ack 9, win 211, options [nop,nop,TS val 27819441 ecr 3788576332], length 0 ^C 10 packets captured 10 packets received by filter 0 packets dropped by kernel

    À partir de la sortie ci-dessus, nous pouvons confirmer que la connexion en trois temps TCP a été terminée en 222 microsecondes (918 091 - 917 869) et que la commande ping a été envoyée et retournée en 173 microsecondes (918 295 - 918 122).

    Il a fallu 438 microsecondes (918 307 - 917 869) entre la demande et la fermeture de la connexion. Ces résultats confirmeraient que les temps de réponse du réseau et du moteur sont bons et que l'enquête peut se concentrer sur d'autres composants.

  • Sur le système d'exploitation : Strace peut contribuer à identifier les écarts de temps au niveau du système d'exploitation. L'analyse des applications réelles serait beaucoup plus étendue et des profileurs d'applications ou des débogueurs spécialisés sont conseillés. L'exemple suivant montre simplement si les composants du système d'exploitation de base fonctionnent comme prévu, sinon une enquête plus approfondie peut s'avérer nécessaire. En utilisant la même commande PING Redis avec strace, nous obtenons :

    $ echo ping | strace -f -tttt -r -e trace=execve,socket,open,recvfrom,sendto nc example.xxxxxx.ng.0001.use1.cache.amazonaws.com (http://example.xxxxxx.ng.0001.use1.cache.amazonaws.com/) 6379 1609430221.697712 (+ 0.000000) execve("/usr/bin/nc", ["nc", "example.xxxxxx.ng.0001.use"..., "6379"], 0x7fffede7cc38 /* 22 vars */) = 0 1609430221.708955 (+ 0.011231) socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3 1609430221.709084 (+ 0.000124) socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3 1609430221.709258 (+ 0.000173) open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3 1609430221.709637 (+ 0.000378) open("/etc/host.conf", O_RDONLY|O_CLOEXEC) = 3 1609430221.709923 (+ 0.000286) open("/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 3 1609430221.711365 (+ 0.001443) open("/etc/hosts", O_RDONLY|O_CLOEXEC) = 3 1609430221.713293 (+ 0.001928) socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 3 1609430221.717419 (+ 0.004126) recvfrom(3, "\362|\201\200\0\1\0\2\0\0\0\0\rnotls20201224\6tihew"..., 2048, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.31.0.2")}, [28->16]) = 155 1609430221.717890 (+ 0.000469) recvfrom(3, "\204\207\201\200\0\1\0\1\0\0\0\0\rnotls20201224\6tihew"..., 65536, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.31.0.2")}, [28->16]) = 139 1609430221.745659 (+ 0.027772) socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3 1609430221.747548 (+ 0.001887) recvfrom(0, 0x7ffcf2f2ca50, 8192, 0, 0x7ffcf2f2c9d0, [128]) = -1 ENOTSOCK (Socket operation on non-socket) 1609430221.747858 (+ 0.000308) sendto(3, "ping\n", 5, 0, NULL, 0) = 5 1609430221.748048 (+ 0.000188) recvfrom(0, 0x7ffcf2f2ca50, 8192, 0, 0x7ffcf2f2c9d0, [128]) = -1 ENOTSOCK (Socket operation on non-socket) 1609430221.748330 (+ 0.000282) recvfrom(3, "+PONG\r\n", 8192, 0, 0x7ffcf2f2c9d0, [128->0]) = 7 +PONG 1609430221.748543 (+ 0.000213) recvfrom(3, "", 8192, 0, 0x7ffcf2f2c9d0, [128->0]) = 0 1609430221.752110 (+ 0.003569) +++ exited with 0 +++

    Dans l'exemple ci-dessus, la commande a pris un peu plus de 54 millisecondes (752 110 - 697 712 = 54 398 microsecondes).

    Un temps important, environ 20 ms, était nécessaire pour instancier nc et effectuer la résolution de nom (de 697 712 à 717 890). Ensuite, 2 ms ont été nécessaires pour créer le socket TCP (745 659 à 747 858), et 0,4 ms (747 858 à 748 330) pour envoyer et recevoir la réponse à la demande.