Im essayant de rendre un graphique de graphite qui a le movingAverage de la somme du hitcount de plusieurs métriques différentes. Cet objectif: Je m'attends à ce que le movingAverage de cette cible: fonctionnerait bien, aussi: Cependant, je reçois la redoutée Aucune image de données à la place. La sortie du format JSON ne fournit pas d'informations utiles dans ce cas non plus, malheureusement, retourner simplement. Comment puis-je calculer la moyenne mobile de la somme ci-dessus dans Graphite Ive a essayé le suivant sans la chance aussi: Merci pour votre helpI obtenir des données en graphite avec une granularité d'une heure. Par exemple, Maintenant, Id aimerait être capable de représenter ce graphique dans l'évolution de la valeur pour chaque jour de la semaine, de sorte que la valeur réelle affichée est la somme (ou la moyenne) des valeurs pour ce jour particulier de la semaine au cours de quelques semaines Disons 2 semaines par exemple). Mon graphique ressemblerait à cela si je regarde seulement la dernière semaine: Par exemple, pour le point du vendredi, il prend les valeurs d'aujourd'hui (1112), la valeur du dernier vendredi (3) et fait une moyenne des deux ( 1112) 3) 2 Est-ce possible, comment résumer (your. metric. goes. here, 1week, sum) va résumer les données en intervalles d'une semaine en les additionnant. Vous pouvez également utiliser avg, max, min. En ce qui concerne la sémantique go-Timers, ont généralement besoin d'être moyennés et les compteurs doivent être additionnés lorsqu'ils sont résumés. Exemple: Si vous mesurez les comptages de tours et les temps de tour lorsque vous exécutez chaque jour, et que vous souhaitez un résumé hebdomadaire, vous faites la moyenne du temps de sept jours et l'attribuez à ce temps hebdomadaire. Avec compte-tours. Il est plus logique de savoir total, donc vous résumer. Sur une autre note: timeStack et timeShift sont utilisés dans les cas où vous souhaitez comparer les données des derniers mois avec ces mois sur la même timeline. En outre, vous pouvez timeShift les données résumées too. Graphite 1 effectue deux tâches assez simples: stocker des nombres qui changent avec le temps et les graphiques. Il ya eu beaucoup de logiciels écrits au fil des ans pour faire ces mêmes tâches. Ce qui rend Graphite unique, c'est qu'elle fournit cette fonctionnalité en tant que service réseau à la fois facile à utiliser et hautement évolutif. Le protocole pour l'alimentation des données en graphite est assez simple pour que vous puissiez apprendre à le faire à la main en quelques minutes (pas que youd voulez vraiment, mais c'est un test litmus décent pour la simplicité). Le rendu des graphiques et la récupération des points de données sont aussi simples que la récupération d'une URL. Cela rend très naturel d'intégrer Graphite avec d'autres logiciels et permet aux utilisateurs de construire des applications puissantes sur le dessus de Graphite. L'une des utilisations les plus courantes de Graphite est la création de tableaux de bord basés sur le Web pour la surveillance et l'analyse. Graphite est né dans un environnement de commerce électronique de haut volume et sa conception reflète cela. L'évolutivité et l'accès en temps réel aux données sont des objectifs clés. Les composants qui permettent à Graphite d'atteindre ces objectifs comprennent une bibliothèque de bases de données spécialisée et son format de stockage, un mécanisme de mise en cache pour optimiser les opérations d'E / S et une méthode simple et efficace de clustering des serveurs Graphite. Plutôt que de simplement décrire comment Graphite fonctionne aujourd'hui, je vais expliquer comment Graphite a été initialement mis en œuvre (assez naïvement), quels problèmes j'ai rencontré, et comment j'ai imaginé des solutions pour eux. 7.1. La bibliothèque de base de données: stocker les données de la série temporelle Le graphite est entièrement écrit en Python et se compose de trois composants principaux: une base de données nommée chuchotement. Un démon de back-end nommé carbone. Et une webapp frontale qui rend des graphiques et fournit une interface utilisateur de base. Alors que whisper a été écrit spécifiquement pour Graphite, il peut également être utilisé de manière indépendante. Il est très semblable dans la conception à la base de données round-robin utilisée par RRDtool, et ne stocke que des données numériques de séries chronologiques. Habituellement, nous pensons que les bases de données sont des processus serveur auxquels les applications clientes parlent sur des sockets. Cependant, murmure. Tout comme RRDtool, est une bibliothèque de base de données utilisée par les applications pour manipuler et récupérer des données stockées dans des fichiers spécialement formatés. Les opérations de chuchotement les plus élémentaires sont créées pour créer un nouveau fichier whisper, mettre à jour pour écrire de nouveaux points de données dans un fichier et extraire pour récupérer des points de données. Figure 7.1: Anatomie de base d'un fichier susurré Comme le montre la figure 7.1. Les fichiers chuchotés se composent d'une section d'en-tête contenant diverses métadonnées, suivie d'une ou plusieurs sections d'archive. Chaque archive est une séquence de points de données consécutifs qui sont des paires (timestamp, value). Lorsqu'une opération de mise à jour ou d'extraction est effectuée, le chuchotement détermine l'offset dans le fichier sur lequel les données doivent être écrites ou lues, en fonction de l'horodatage et de la configuration de l'archive. 7.2. Le back-end: un service de stockage simple Graphites back-end est un processus de démon appelé carbon-cache. Généralement appelé simplement carbone. Il est construit sur Twisted, un framework d'E / S événementielle hautement évolutif pour Python. Twisted permet au carbone de parler efficacement à un grand nombre de clients et de gérer une grande quantité de trafic avec des frais généraux faibles. La figure 7.2 montre le flux de données entre le carbone. Chuchotement et le webapp: Les applications de client rassemblent des données et l'envoient à l'extrémité arrière de graphite, carbone. Qui stocke les données en utilisant chuchotement. Ces données peuvent ensuite être utilisées par la webapp Graphite pour générer des graphiques. Figure 7.2: Flux de données La principale fonction du carbone est de stocker des points de données pour les métriques fournies par les clients. Dans la terminologie graphite, une métrique est une quantité mesurable qui peut varier dans le temps (comme l'utilisation de l'UC d'un serveur ou le nombre de ventes d'un produit). Un point de données est simplement une paire (timestamp, value) correspondant à la valeur mesurée d'une métrique particulière à un moment donné. Les métriques sont identifiées de façon unique par leur nom, et le nom de chaque métrique ainsi que ses points de données sont fournis par les applications clientes. Un type commun d'application client est un agent de surveillance qui collecte les métriques du système ou de l'application et envoie ses valeurs collectées au carbone pour faciliter le stockage et la visualisation. Les métriques dans Graphite ont des noms hiérarchiques simples, semblables aux chemins du système de fichiers, sauf qu'un point est utilisé pour délimiter la hiérarchie plutôt qu'une barre oblique ou une barre oblique inverse. Le carbone respectera n'importe quel nom légal et créera un fichier de whisper pour chaque métrique pour stocker ses points de données. Les fichiers de chuchotement sont stockés dans le répertoire de données de carbone dans une hiérarchie de système de fichiers qui reflète la hiérarchie délimitée par points dans chaque nom de métrique, de sorte que (par exemple) serveurs. www01.cpuUsage mappe à hellipserverswww01cpuUsage. wsp. Lorsqu'une application cliente souhaite envoyer des points de données à Graphite, elle doit établir une connexion TCP au carbone. Généralement sur le port 2003 2. Le client fait tout le charbon parlant n'envoie rien sur la connexion. Le client envoie des points de données dans un format texte simple tandis que la connexion peut être laissée ouverte et réutilisée si nécessaire. Le format est une ligne de texte par point de données où chaque ligne contient le nom de la métrique en pointillés, la valeur et un horodatage d'époque Unix séparés par des espaces. Par exemple, un client peut envoyer: Sur un niveau élevé, tout le carbone est d'écouter les données dans ce format et essayer de le stocker sur le disque aussi rapidement que possible à l'aide de murmurer. Plus tard, nous discuterons des détails de certaines astuces utilisées pour assurer l'évolutivité et obtenir les meilleures performances que nous pouvons sortir d'un disque dur typique. 7.3. Le front-end: Graphiques à la demande Le graphite webapp permet aux utilisateurs de demander des graphes personnalisés avec une simple API basée sur URL. Les paramètres graphiques sont spécifiés dans la requête-chaîne d'une requête HTTP GET et une image PNG est renvoyée en réponse. Par exemple, l'URL: demande un graphique 500times300 pour les serveurs de métrique. www01.cpuUsage et les dernières 24 heures de données. En fait, seul le paramètre cible est requis, tous les autres sont optionnels et utilisez vos valeurs par défaut si vous les omettez. Graphite prend en charge une grande variété d'options d'affichage ainsi que des fonctions de manipulation de données qui suivent une simple syntaxe fonctionnelle. Par exemple, nous pourrions représenter graphiquement une moyenne mobile de 10 points de la métrique dans notre exemple précédent de la façon suivante: Les fonctions peuvent être imbriquées, ce qui permet des expressions et des calculs complexes. Voici un autre exemple qui donne le total courant des ventes pour la journée en utilisant les métriques par produit de ventes par minute: La fonction sumSeries calcule une série temporelle qui est la somme de chaque métrique correspondant aux produits pattern..salesPerMinute. Ensuite, l'intégrale calcule un total courant plutôt qu'un comptage par minute. De là, il n'est pas trop difficile d'imaginer comment on pourrait construire une interface Web pour visualiser et manipuler des graphiques. Graphite est livré avec sa propre interface utilisateur Composer, illustrée à la figure 7.3. Qui fait cela en utilisant Javascript pour modifier les paramètres des URL graphiques que l'utilisateur clique dans les menus des fonctionnalités disponibles. Figure 7.3: Interface Graphites Composer 7.4. Dashboards Depuis sa création, Graphite a été utilisé comme outil de création de tableaux de bord basés sur le Web. L'URL API en fait un cas d'utilisation naturelle. Créer un tableau de bord est aussi simple que faire une page HTML pleine de balises comme celle-ci: Cependant, tout le monde n'aime pas l'élaboration d'URL à la main, donc Graphistes Composer UI fournit une méthode point-and-click pour créer un graphique à partir duquel vous pouvez simplement copier et Coller l'URL. Lorsqu'il est couplé avec un autre outil qui permet la création rapide de pages Web (comme un wiki), cela devient assez facile que les utilisateurs non techniques peuvent construire leurs propres tableaux de bord assez facilement. 7.5. Un fossé évident Une fois que mes utilisateurs ont commencé à créer des tableaux de bord, Graphite a rapidement commencé à avoir des problèmes de performance. J'ai enquêté sur les journaux du serveur Web pour voir ce que les requêtes étaient bogging il vers le bas. Il était assez évident que le problème était le grand nombre de requêtes graphiques. Le webapp était CPU-bound, rendant graphiques en permanence. J'ai remarqué qu'il y avait beaucoup de demandes identiques, et les tableaux de bord étaient à blâmer. Imaginez que vous ayez un tableau de bord contenant 10 graphiques et que la page soit actualisée une fois par minute. Chaque fois qu'un utilisateur ouvre le tableau de bord dans son navigateur, Graphite doit traiter 10 demandes de plus par minute. Cela devient rapidement coûteux. Une solution simple est de rendre chaque graphe une seule fois, puis de servir une copie de celui-ci à chaque utilisateur. Le framework Web de Django (sur lequel Graphite est construit) offre un excellent mécanisme de mise en cache qui peut utiliser différents backend comme memcached. Memcached 3 est essentiellement une table de hachage fournie en tant que service de réseau. Les applications clientes peuvent obtenir et définir des paires clé-valeur tout comme une table de hachage ordinaire. Le principal avantage de l'utilisation de memcached est que le résultat d'une demande coûteuse (comme le rendu d'un graphe) peut être stocké très rapidement et récupéré plus tard pour traiter les demandes suivantes. Pour éviter de renvoyer les mêmes graphiques périmés, memcached peut être configuré pour expirer les graphes mis en cache après une courte période. Même si ce n'est que quelques secondes, le fardeau qu'il prend Graphite est énorme parce que les demandes en double sont si communs. Un autre cas courant qui crée beaucoup de requêtes de rendu est lorsqu'un utilisateur modifie les options d'affichage et applique des fonctions dans l'interface utilisateur Composer. Chaque fois que l'utilisateur change quelque chose, Graphite doit redessiner le graphe. Les mêmes données sont impliquées dans chaque demande de sorte qu'il est logique de mettre les données sous-jacentes dans le memcache ainsi. Cela maintient l'interface utilisateur réactive à l'utilisateur parce que l'étape de récupération des données est ignorée. 7.6. Optimisation de l'IO Imaginez que vous avez 60 000 mesures que vous envoyez à votre serveur Graphite et que chacune de ces mesures a un point de données par minute. N'oubliez pas que chaque métrique a son propre fichier de chuchotement sur le système de fichiers. Cela signifie que le carbone doit effectuer une opération d'écriture à 60 000 fichiers différents chaque minute. Tant que le carbone peut écrire à un fichier chaque milliseconde, il devrait être capable de suivre. Ce n'est pas trop loin cher, mais disons que vous avez 600 000 métriques mise à jour chaque minute, ou vos statistiques sont mises à jour chaque seconde, ou peut-être vous ne pouvez pas se permettre un stockage assez rapide. Quoi qu'il en soit, supposons que le taux de points de données entrants dépasse le taux d'écriture que votre stockage peut suivre. Comment cette situation doit-elle être gérée? La plupart des disques durs disposent aujourd'hui d'un temps de recherche lent 4. C'est-à-dire le délai entre les opérations IO à deux emplacements différents par rapport à l'écriture d'une séquence contiguë de données. Cela signifie que l'écriture plus contiguë que nous faisons, plus le débit que nous obtenons. Mais si nous avons des milliers de fichiers qui doivent être écrits fréquemment, et chaque écriture est très petite (un seul point de données whisper est seulement 12 octets), alors nos disques vont certainement passer la plupart de leur temps à chercher. En travaillant sous l'hypothèse que le taux d'écriture a un plafond relativement bas, la seule façon d'augmenter notre débit de points de données au-delà de ce taux est d'écrire plusieurs points de données en une seule opération d'écriture. Ceci est possible parce que le murmure arrange des points de données consécutifs sur le disque. J'ai donc ajouté une fonction updatemany pour chuchoter. Qui prend une liste de points de données pour une seule métrique et compose des points de données contigus en une seule opération d'écriture. Même si cela rend chaque écriture plus grande, la différence de temps qu'il faut pour écrire dix points de données (120 octets) par rapport à un point de données (12 octets) est négligeable. Il faut beaucoup plus de points de données avant que la taille de chaque écriture commence à affecter sensiblement la latence. Ensuite, j'ai implémenté un mécanisme tampon en carbone. Chaque point de données entrant est mappé à une file d'attente en fonction de son nom de métrique et est ensuite ajouté à cette file d'attente. Un autre thread itérativement à travers toutes les files d'attente et pour chacune d'elles il extrait tous les points de données et les écrit dans le fichier whisper approprié avec updatemany. Pour en revenir à notre exemple, si 600 000 métriques sont mises à jour à chaque minute et que notre stockage ne peut que 1 écriture par milliseconde, les files d'attente finiront par contenir environ 10 points de données en moyenne. La seule ressource qui nous en coûte est la mémoire, qui est relativement abondante puisque chaque point de données est seulement quelques octets. Cette stratégie tampon dynamiquement autant de points de données que nécessaire pour maintenir un taux de points de données entrants qui peuvent dépasser le taux d'opérations IO votre stockage peut suivre avec. Un avantage appréciable de cette approche est qu'elle ajoute un certain degré de résilience pour gérer les ralentissements IO temporaires. Si le système doit effectuer d'autres travaux d'E / S hors graphite, il est probable que le taux d'écriture diminuera, auquel cas les files d'attente en carbone s croîtront simplement. Plus les files d'attente sont grandes, plus les écritures sont grandes. Etant donné que le débit total des points de données est égal au taux d'écriture des opérations multiplié par la taille moyenne de chaque écriture, le carbone est capable de se maintenir tant qu'il y a suffisamment de mémoire pour les files d'attente. Le mécanisme de mise en file d'attente du carbone s est représenté à la figure 7.4. Figure 7.4: Mécanisme de mise en file d'attente des carbones 7.7. Le maintien en temps réel des points de données de tamponnement a été une bonne façon d'optimiser l'IO de carbone, mais il n'a pas pris longtemps pour mes utilisateurs de remarquer un effet secondaire plutôt troublant. Revoir notre exemple encore une fois, nous avons 600 000 métriques qui se mettent à jour chaque minute et supposaient que notre stockage ne peut suivre que 60 000 opérations d'écriture par minute. Cela signifie que nous aurons approximativement 10 minutes de données se trouvant dans les files d'attente de carbone à un moment donné. Pour un utilisateur cela signifie que les graphes qu'ils demandent à la graphite webapp manqueront les 10 dernières minutes de données: Pas bon Heureusement, la solution est assez simple. J'ai simplement ajouté un écouteur socket à carbone qui fournit une interface de requête pour accéder aux points de données en mémoire tampon, puis modifie le graphite webapp pour utiliser cette interface chaque fois qu'il a besoin pour récupérer des données. Le webapp combine alors les points de données qu'il récupère du carbone avec les points de données qu'il a récupérés du disque et voila, les graphiques sont en temps réel. Certes, dans notre exemple les points de données sont mis à jour à la minute et donc pas exactement en temps réel, mais le fait que chaque point de données est instantanément accessible dans un graphe une fois qu'il est reçu par le carbone est en temps réel. 7.8. Les noyaux, les caches et les défaillances catastrophiques Comme il est probablement évident à l'heure actuelle, une caractéristique clé de la performance du système que Graphites possède sa propre performance dépend de sa latence IO. Jusqu'à présent, nous avons supposé que notre système a constamment faible latence IO moyennant environ 1 milliseconde par écriture, mais c'est une grande hypothèse qui nécessite une analyse un peu plus profonde. La plupart des disques durs simplement arent que rapide même avec des dizaines de disques dans une matrice RAID il est très probable que plus de 1 millisecond de latence pour l'accès aléatoire. Pourtant, si vous étiez à essayer de tester à quelle vitesse même un ordinateur portable vieux pourrait écrire un kilo-octet entier sur le disque, vous trouverez que l'appel du système d'écriture retourne en beaucoup moins de 1 milliseconde. Pourquoi? Chaque fois que le logiciel a des caractéristiques de performance incohérentes ou inattendues, généralement le buffering ou la mise en cache est à blâmer. Dans le cas présent, il s'agissait des deux. L'appel de système d'écriture ne techniquement pas écrire vos données sur le disque, il met simplement dans un tampon que le noyau écrit ensuite sur le disque plus tard. C'est pourquoi l'appel d'écriture revient habituellement si rapidement. Même après que le tampon a été écrit sur le disque, il reste souvent mis en cache pour les lectures suivantes. Ces deux comportements, la mise en mémoire tampon et la mise en cache, nécessitent évidemment de la mémoire. Les développeurs du noyau, étant les gens intelligents qu'ils sont, a décidé qu'il serait une bonne idée d'utiliser n'importe quelle mémoire d'espace utilisateur est actuellement libre au lieu d'allouer la mémoire pure et simple. Cela s'avère être un booster de la performance extrêmement utile et il explique également pourquoi peu importe la quantité de mémoire que vous ajoutez à un système, il finira généralement par avoir presque nulle mémoire libre après avoir fait une modeste quantité d'E / S. Si vos applications d'espace utilisateur ne sont pas en utilisant cette mémoire, votre noyau est probablement. L'inconvénient de cette approche est que cette mémoire libre peut être retirée du noyau au moment où une application utilisateur-espace décide qu'il doit allouer plus de mémoire pour lui-même. Le noyau n'a d'autre choix que de renoncer à lui, en perdant les tampons qui pourraient avoir été là. Alors, qu'est-ce que tout cela signifie pour Graphite Nous venons de mettre en évidence la dépendance carbone sur la latence E / S toujours faible et nous savons également que l'appel système write retourne rapidement parce que les données est simplement être copié dans un tampon. Ce qui se produit quand il n'y a pas assez de mémoire pour que le noyau continue de tamponner des écritures Les écritures deviennent synchrones et donc terriblement lentes Cela provoque une chute dramatique dans le taux d'opérations d'écriture du carbone, ce qui provoque des files d'attente carbone s qui mange encore plus Mémoire, affamant le noyau encore plus loin. En fin de compte, ce genre de situation se traduit habituellement par un manque de mémoire dans le carbone ou un système d'administration en colère. Pour éviter ce type de catastrophe, j'ai ajouté plusieurs fonctionnalités au carbone, y compris des limites configurables sur le nombre de points de données peuvent être mis en file d'attente et les limites de débit sur la rapidité avec laquelle différentes opérations de chuchotement peuvent être effectuées. Ces caractéristiques peuvent protéger le carbone contre la spirale hors de contrôle et au lieu d'imposer des effets moins durs comme la chute de certains points de données ou de refuser d'accepter plus de points de données. Toutefois, les valeurs appropriées pour ces paramètres sont spécifiques au système et nécessitent un nombre suffisant de tests à régler. Ils sont utiles, mais ils ne résolvent pas fondamentalement le problème. Pour cela, bien besoin de plus de matériel. 7.9. Mise en grappe La création de plusieurs serveurs Graphite semble être un système unique, du point de vue de l'utilisateur, n'est pas terriblement difficile, du moins pour une implémentation naiumlve. L'interaction utilisateur webapps se compose principalement de deux opérations: trouver des métriques et extraire des points de données (généralement sous forme de graphique). Les opérations de recherche et d'extraction de la webapp sont cachées dans une bibliothèque qui résume leur mise en œuvre du reste de la base de code et sont également exposées par des gestionnaires de requêtes HTTP pour des appels distants faciles. L'opération de recherche recherche dans le système de fichiers local des données chuchotées pour les objets correspondant à un motif spécifié par l'utilisateur, tout comme un système de fichiers glob comme. txt correspond aux fichiers avec cette extension. Étant une structure arborescente, le résultat renvoyé par find est une collection d'objets Node, chacun dérivant des sous-classes Branch ou Leaf de Node. Les répertoires correspondent aux nœuds de branche et les fichiers de chuchotement correspondent aux nœuds de feuille. Cette couche d'abstraction facilite le support de différents types de stockage sous-jacent, y compris les fichiers RRD 5 et les fichiers chuchotés gzipés. L'interface Feuille définit une méthode d'extraction dont l'implémentation dépend du type de noeud feuille. Dans le cas des fichiers whisper, il s'agit simplement d'une mince enveloppe autour de la propre fonction de récupération des bibliothèques de murmures. Lorsque le support de cluster a été ajouté, la fonction de recherche a été étendue pour pouvoir effectuer des appels de recherche à distance via HTTP vers d'autres serveurs Graphite spécifiés dans la configuration des webapps. Les données de nœud contenues dans les résultats de ces appels HTTP sont enveloppées en tant qu'objets RemoteNode conformes au nœud habituel. Branche. Et des interfaces Leaf. Cela rend le clustering transparent pour le reste de la base de code webapps. La méthode fetch pour un nœud feuille éloigné est implémentée comme un autre appel HTTP pour récupérer les points de données du serveur graphite de nœuds. Tous ces appels sont effectués entre les webapps de la même manière qu'un client les appellerait, sauf avec un paramètre supplémentaire spécifiant que l'opération ne devrait être effectuée que localement et ne pas être redistribuée dans l'ensemble du cluster. Lorsque le webapp est invité à rendre un graphique, il effectue l'opération find pour localiser les métriques demandées et les appels chercher sur chacun pour récupérer leurs points de données. Cela fonctionne que les données soient sur le serveur local, les serveurs distants ou les deux. Si un serveur tombe en panne, le délai d'attente des appels à distance est assez rapide et le serveur est marqué comme étant hors service pendant une courte période au cours de laquelle aucun appel supplémentaire ne sera effectué. Du point de vue de l'utilisateur, toutes les données sur le serveur perdu seront absentes de leurs graphiques à moins que ces données soient dupliquées sur un autre serveur du cluster. 7.9.1. Une brève analyse de l'efficacité du clustering La partie la plus coûteuse d'une requête graphique est de rendre le graphique. Chaque rendu est exécuté par un seul serveur de sorte ajouter plus de serveurs effectivement augmenter la capacité de rendu des graphes. Cependant, le fait que de nombreuses demandes finissent par distribuer des appels de recherche à tous les autres serveurs de la grappe signifie que notre système de regroupement partage une grande partie de la charge frontale plutôt que de la disperser. Ce que nous avons réalisé à ce stade, cependant, est un moyen efficace de distribuer la charge de back-end, car chaque instance de carbone fonctionne de façon indépendante. C'est une bonne première étape puisque la plupart du temps l'arrière est un goulet d'étranglement bien avant l'extrémité avant est, mais clairement l'extrémité avant ne sera pas à l'échelle horizontale avec cette approche. Afin de rendre l'échelle frontale plus efficace, le nombre d'appels de recherche à distance effectués par le webapp doit être réduit. Encore une fois, la solution la plus simple est la mise en cache. Tout comme memcached est déjà utilisé pour mettre en cache les points de données et les graphiques rendus, il peut également être utilisé pour mettre en cache les résultats des requêtes de recherche. Étant donné que l'emplacement des métriques est beaucoup moins susceptible de changer fréquemment, cela devrait généralement être mis en cache plus longtemps. Le compromis de définir le délai d'attente du cache pour trouver les résultats trop longs, c'est que les nouvelles métriques ajoutées à la hiérarchie peuvent ne pas apparaître aussi rapidement pour l'utilisateur. 7.9.2. Distribution de métriques dans un cluster Le graphite webapp est assez homogène dans un cluster, en ce sens qu'il effectue exactement le même travail sur chaque serveur. Toutefois, le rôle de carbone peut varier d'un serveur à l'autre en fonction des données que vous choisissez d'envoyer à chaque instance. Souvent, il existe de nombreux clients différents qui envoient des données au carbone. Il serait donc assez ennuyeux de coupler chaque configuration clients avec votre grappe graphite mise en page. Les métriques d'application peuvent aller à un serveur de carbone, tandis que les métriques métier peuvent être envoyées à plusieurs serveurs de carbone pour la redondance. Pour simplifier la gestion de scénarios comme celui-ci, Graphite est livré avec un outil supplémentaire appelé relais de carbone. Son travail est assez simple, il reçoit des données métriques de clients exactement comme le démon de carbone standard (qui est en fait nommé carbone-cache), mais au lieu de stocker les données, il applique un ensemble de règles aux noms de métrique pour déterminer quels serveurs de cache de carbone Pour relayer les données. Chaque règle se compose d'une expression régulière et d'une liste de serveurs de destination. Pour chaque point de données reçu, les règles sont évaluées dans l'ordre et la première règle dont l'expression régulière correspond au nom de la métrique est utilisée. De cette façon, tous les clients ont besoin de faire est d'envoyer leurs données au relais de carbone et il finira sur les bons serveurs. En un sens, le relais de carbone fournit une fonctionnalité de réplication, mais il serait plus précisément appelé duplication d'entrée car il ne traite pas de problèmes de synchronisation. Si un serveur tombe en panne temporairement, il manquera les points de données pour la période pendant laquelle il était en panne, mais fonctionnent normalement. Il existe des scripts administratifs qui laissent le contrôle du processus de resynchronisation entre les mains de l'administrateur système. 7.10. Réflexions sur le design Mon expérience de travail sur Graphite a réaffirmé mon conviction que l'évolutivité a très peu à voir avec les performances de bas niveau, mais est plutôt un produit de conception globale. J'ai rencontré de nombreux goulets d'étranglement en cours de route, mais chaque fois que je cherche des améliorations dans la conception plutôt que des accélérations dans la performance. On m'a demandé à plusieurs reprises pourquoi j'ai écrit Graphite en Python plutôt que Java ou C, et ma réponse est toujours que je n'ai pas encore rencontré un vrai besoin de la performance qu'une autre langue pourrait offrir. Dans Knu74, Donald Knuth dit célèbre que l'optimisation prématurée est la racine de tout le mal. Tant que nous supposons que notre code va continuer à évoluer de manière non triviale, alors toute optimisation 6 est dans un certain sens prématurée. L'une des plus grandes forces et des plus grandes faiblesses de Graphites est le fait que très peu de lui a été réellement conçu dans le sens traditionnel. En gros, le graphite évoluait graduellement, obstacle par obstacle, à mesure que se posaient des problèmes. Plusieurs fois, les obstacles étaient prévisibles et diverses solutions préventives semblaient naturelles. Cependant, il peut être utile d'éviter de résoudre des problèmes que vous n'avez pas encore, même si il semble probable que vous allez bientôt. La raison en est que vous pouvez apprendre beaucoup plus d'étroitement étudier les échecs réels que de théoriser sur les stratégies supérieures. La résolution de problèmes est guidée par les données empiriques que nous avons à portée de main et notre propre connaissance et intuition. J'ai trouvé que doutant de votre propre sagesse peut vous forcer à regarder vos données empiriques plus complètement. Par exemple, lorsque j'ai écrit pour la première fois un chuchotement, j'étais convaincu qu'il faudrait le réécrire en C pour la vitesse et que ma mise en œuvre Python servirait seulement de prototype. Si je werent sous un temps-crunch je très bien pu avoir sauté la mise en œuvre de Python entièrement. Il s'avère cependant que IO est un goulet d'étranglement beaucoup plus tôt que le CPU que la moindre efficacité de Python importe peu dans la pratique. Comme je l'ai dit, cependant, l'approche évolutive est aussi une grande faiblesse du graphite. Il s'avère que les interfaces ne se prêtent pas bien à une évolution graduelle. Une bonne interface est cohérente et utilise des conventions pour maximiser la prévisibilité. Par cette mesure, Graphites URL API est actuellement une interface de sous-pair à mon avis. Les options et les fonctions ont été rattachées au fil du temps, formant parfois de petites îles de cohérence, mais globalement dépourvues d'un sens global de cohérence. La seule façon de résoudre un tel problème est de contrôler les versions des interfaces, mais cela a aussi des inconvénients. Une fois qu'une nouvelle interface est conçue, la vieille est encore difficile à se débarrasser, s'attardant autour comme des bagages évolutifs comme l'appendice humain. Il peut sembler assez inoffensif jusqu'à ce qu'un jour votre code obtient l'appendicite (c'est-à-dire un bug attaché à l'ancienne interface) et vous êtes forcé de fonctionner. Si je devais changer une chose au sujet de Graphite tôt, il aurait été de prendre beaucoup plus de soin dans la conception des API externes, en pensant à l'avance au lieu de les évoluer peu à peu. Un autre aspect du graphite qui provoque une certaine frustration est la flexibilité limitée du modèle hiérarchique de nomenclature métrique. Bien qu'il soit assez simple et très pratique pour la plupart des cas d'utilisation, il rend certaines requêtes sophistiquées très difficile, voire impossible, à exprimer. Quand j'ai pensé pour la première fois à créer Graphite, je savais dès le début que je voulais une API URL éditable par l'homme pour la création de graphiques 7. Alors que je suis toujours heureux que Graphite offre ceci aujourd'hui, Im a peur cette exigence a chargé l'API avec une syntaxe trop simple que Rend les expressions complexes lourdes. Une hiérarchie rend le problème de la détermination de la clé primaire pour une métrique assez simple, car un chemin est essentiellement une clé primaire pour un nœud dans l'arborescence. L'inconvénient est que toutes les données descriptives (c'est-à-dire les données de colonne) doivent être incorporées directement dans le chemin. Une solution potentielle est de maintenir le modèle hiérarchique et d'ajouter une base de données de métadonnées distincte pour permettre une sélection plus avancée des métriques avec une syntaxe spéciale. 7.11. Devenir une source ouverte En regardant l'évolution de Graphite, je suis toujours surpris à la fois par la mesure dans laquelle il est venu en tant que projet et par la mesure dans laquelle il m'a pris en tant que programmeur. Il a commencé comme un projet animal qui était seulement quelques centaines de lignes de code. Le moteur de rendu a commencé comme une expérience, simplement pour voir si je pouvais en écrire un. Chuchote a été écrit au cours d'un week-end de désespoir pour résoudre un problème show-stopper avant une date de lancement critique. Le carbone a été réécrit plus de fois que je me soucie de me souvenir. Une fois que j'ai été autorisé à libérer Graphite sous une licence open source en 2008 je n'ai jamais vraiment attendu beaucoup de réponse. Après quelques mois, il a été mentionné dans un article CNET qui a été ramassé par Slashdot et le projet a soudainement décollé et a été actif depuis. Aujourd'hui, il existe des dizaines de grandes et moyennes entreprises utilisant Graphite. La communauté est très active et continue de croître. Loin d'être un produit fini, il ya beaucoup de travail expérimental frais qui est fait, ce qui le rend amusant de travailler et plein de potentiel. Launchpad. netgraphite Il existe un autre port sur lequel des objets sérialisés peuvent être envoyés, ce qui est plus efficace que le format texte brut. Cela n'est nécessaire que pour des niveaux de trafic très élevés. Memcached. org Les lecteurs à semi-conducteurs ont généralement des temps de recherche extrêmement rapides par rapport aux disques durs classiques. Les fichiers RRD sont en fait des nœuds de branche car ils peuvent contenir plusieurs sources de données. Une source de données RRD est un nœud feuille. Knuth a spécifiquement voulu dire l'optimisation de code à bas niveau, pas l'optimisation macroscopique telle que des améliorations de conception. Cela oblige les graphiques eux-mêmes à être open source. Tout le monde peut simplement regarder un graphique URL pour le comprendre ou le modifier.
No comments:
Post a Comment