Presto est un moteur de requête SQL gratuit publié en Open Source. Nous l’utilisons depuis 10 ans chez Meta, et nous avons tiré de nombreux enseignements de cette expérience. L’exécution à grande échelle de l’ensemble des outils, processus et services a fait surgir certains problèmes imprévus qu’il nous a fallu surmonter. Vous trouverez ci-dessous 4 leçons que nous avons apprises lorsque nous avons étendu Presto à l’échelle de Meta, ainsi que quelques conseils au cas où vous souhaiteriez exécuter vos propres requêtes à grande échelle.
Figure 1 : Workflow du processus d’envoi des nouvelles versions de Presto (diagramme conçu par Philip S. Bell)
Meta exécute un grand nombre de clusters Presto couvrant des data centers répartis dans le monde entier. En règle générale, une nouvelle version de Presto est conçue et prête à être déployée une fois par mois, voire deux. L’un des premiers défis auxquels nous avons été confrontés, alors que l’utilisation de Presto chez Meta s’intensifiait rapidement, a été de déployer le moteur de requête sur un grand nombre de clusters tout en garantissant une disponibilité et une fiabilité en continu. Cela reste particulièrement vrai pour les cas d’utilisation interactifs de Presto, c’est-à-dire lorsqu’une personne exécute une requête dont elle attend activement le résultat. L’échec des requêtes se révèle moins problématique pour les cas d’utilisation « par lots » automatisés, dans le cadre desquels les nouvelles tentatives automatiques garantissent l’aboutissement final d’une requête.
Nous avons résolu facilement ce problème. Tous les clusters Presto sont placés derrière un équilibreur de charge baptisé Gateway (passerelle), qui est chargé (en association avec d’autres systèmes chez Meta) d’acheminer les requêtes Presto vers le cluster approprié. Lorsqu’un cluster Presto doit être mis à jour, il est d’abord identifié comme étant retiré du Gateway, ce qui signifie que le Gateway cesse d’acheminer de nouvelles requêtes vers ce cluster. Ensuite, l’automatisation attend la fin des requêtes en cours d’exécution sur le cluster pendant un laps de temps prédéterminé. Puis le cluster est mis à jour, après quoi il est remis en ligne et rendu visible pour le Gateway, lequel peut alors recommencer à acheminer de nouvelles requêtes vers ce cluster.
L’autre aspect du déploiement des nouvelles versions de Presto concerne la disponibilité. Nous devons nous assurer que les utilisateur·ices peuvent continuer à tirer parti de Presto pendant que les clusters sont mis à jour. Là encore, l’automatisation offre l’assurance que tous les data centers de chaque région physique disposent systématiquement du nombre de clusters Presto nécessaire. Bien entendu, il convient de parvenir à un équilibre entre le retrait simultané d’un nombre de clusters excessif (ce qui occasionne alors un problème de disponibilité) et celui d’un nombre de clusters insuffisant (ce qui allonge sensiblement la durée du déploiement).
Figure 2 : Workflow automatisé de l’ajout de matériel aux clusters (diagramme conçu par Philip S. Bell)
La répartition de l’entrepôt de données de Meta entre différentes régions est en constante évolution. Cela signifie que de nouveaux clusters Presto doivent être mis en service, alors que des clusters existants sont régulièrement désactivés. Auparavant, lorsqu’il n’existait qu’un petit nombre de clusters Presto, ce processus était effectué manuellement. Mais lorsque Meta a commencé à prendre de l’essor, il est vite devenu difficile de suivre l’ensemble des modifications manuellement. Pour résoudre ce problème, nous avons entrepris d’automatiser la mise en service et la désactivation des clusters.
Pour commencer, nous avons été contraints de standardiser les configurations de nos clusters. Autrement dit, nous avons dû créer des configurations de base pour les différents cas d’utilisation de Presto chez Meta. Nous avons ensuite attribué à chaque cluster un petit nombre de spécifications supplémentaires ou modifiées par rapport à la configuration de base. À l’issue de ce processus, il est ainsi devenu possible d’activer n’importe quel nouveau cluster en générant automatiquement des configurations à partir du modèle de base. L’activation des clusters a également nécessité une intégration avec des crochets d’automatisation afin de s’intégrer aux différents services d’infrastructure à l’échelle de l’entreprise tels que Tupperware et les services propres à l’entrepôt de données. Une fois qu’un cluster est mis en ligne, quelques requêtes de test lui sont envoyées, et l’automatisation vérifie qu’il les exécute correctement. Ensuite, le cluster est inscrit auprès du Gateway, après quoi il commence à prendre en charge les requêtes.
La désactivation d’un cluster suit quasiment le processus inverse. Le cluster est désinscrit du Gateway, et l’automatisation attend que toutes les requêtes en cours aient fini de s’exécuter. Puis les processus Presto sont arrêtés, et les configurations du cluster sont supprimées.
Cette automatisation est intégrée au workflow de mise en service et de désactivation du matériel pour l’entrepôt de données. Nous sommes ainsi parvenus à automatiser la totalité du processus, qu’il s’agisse de la réception d’un nouveau matériel au niveau d’un data center, de la mise en ligne des clusters Presto et de leur prise en charge des requêtes, ou de l’arrêt des clusters lors de la désactivation du matériel. Cette implémentation a permis d’économiser de précieuses heures de travail, de réduire la durée d’inactivité du matériel et de minimiser les risques d’erreur humaine.
Figure 3 : Détection des hôtes défaillants (diagramme conçu par Philip S. Bell)
Face à ce déploiement d’envergure de Presto au sein de Meta, nous avons impérativement dû mettre en place des outils et des mécanismes d’automatisation afin de faciliter la tâche du service d’appel (point de contact concernant Presto).
Au fil des années, nous avons conçu plusieurs « analyseurs » pour aider le service d’appel à débuguer efficacement les problèmes qui surviennent et à en déterminer la cause profonde. Des systèmes de surveillance déclenchent des alertes en cas de violation des accords de niveau de service (ou SLA pour Service Level Agreement) destinés à la clientèle. Les analyseurs se déclenchent alors. Ils tirent leurs informations d’un large éventail de systèmes de surveillance (magasin de données opérationnelles ou ODS pour Operational Data Store), d’évènements publiés sur Scuba, et même de journaux au niveau des hôtes. La logique personnalisée de l’analyseur relie ensuite toutes ces informations pour déterminer la cause profonde probable du problème. Cette approche se révèle d’une grande utilité en présentant l’analyse de la cause profonde au service d’appel, lequel est alors en mesure de se concentrer directement sur les solutions potentielles. Dans certains cas, nous avons entièrement automatisé les processus de débug et de résolution, de sorte que l’intervention du service d’appel n’est même pas nécessaire. En voici quelques exemples :
En exécutant Presto à grande échelle sur une multitude de machines, nous avons remarqué que certains hôtes « défaillants » provoquaient parfois un nombre excessif d’échecs de requêtes. Suite à nos investigations, nous avons identifié quelques causes profondes de la défaillance de ces hôtes, en particulier :
Pour lutter contre ce problème, nous surveillons désormais les échecs de requêtes dans les clusters Presto. Plus précisément, nous nous efforçons, dans la mesure du possible, d’attribuer chaque échec de requête à l’hôte qui en est à l’origine. Nous configurons également des alertes qui se déclenchent lorsqu’un nombre anormalement élevé d’échecs de requêtes est attribué à des hôtes spécifiques. L’automatisation prend alors le relais pour retirer l’hôte de la flotte Presto et ainsi enrayer les échecs.
Chaque cluster Presto prend en charge la mise en file d’attente des requêtes qui lui sont adressées dès qu’il atteint le nombre maximal de requêtes qu’il peut exécuter simultanément, basé sur le cas d’utilisation, la configuration du matériel et la taille des requêtes. Meta a mis en place un mécanisme d’acheminement élaboré, selon lequel une requête Presto est distribuée au cluster qui se révèle capable de l’exécuter tout en optimisant l’utilisation des ressources. Plusieurs systèmes situés au-delà de Presto interviennent dans la prise de décision concernant l’acheminement des requêtes et tiennent compte de différents facteurs :
Du fait de cette complexité, le centre d’appel peut avoir de grandes difficultés à déterminer la cause profonde des problèmes de mise en file d’attente rencontrés en production. Cela constitue un autre exemple dans lequel les analyseurs entrent en jeu en récupérant des informations auprès de différentes sources et en présentant leurs conclusions.
Figure 4 : Fiabilité des équilibreurs de charge (diagramme conçu par Philip S. Bell)
Comme indiqué précédemment, nos clusters Presto sont situés derrière des équilibreurs de charge qui acheminent chaque requête Presto chez Meta. À l’origine, lorsque l’utilisation de Presto en interne était bien moindre qu’aujourd’hui, le Gateway était d’une grande simplicité. Toutefois, à mesure que l’utilisation de Presto au sein de Meta s’est répandue, nous avons rencontré à plusieurs reprises des problèmes d’évolutivité. Par exemple, une situation de forte charge entraînait une défaillance du Gateway, et Presto devenait alors parfois inaccessible à l’ensemble des utilisateur·ices. Certains problèmes de stabilité émanaient principalement du fait qu’un service bombardait accidentellement le Gateway de millions de requêtes dans un court laps de temps, occasionnant ainsi le blocage des processus du Gateway et l’impossibilité d’acheminer la moindre requête.
Pour éviter un tel scénario, nous avons entrepris d’améliorer la fiabilité du Gateway, ainsi que sa capacité à prendre en charge ce pic de trafic inattendu de type déni de service (ou DDoS pour Distributed Denial of Service). Nous avons implémenté une fonctionnalité de limitation des tentatives d’accès, qui rejette les requêtes en situation de forte charge. La limitation des tentatives d’accès peut être activée sur la base du nombre de requêtes par seconde selon différentes dimensions, par exemple par utilisateur·ice, par source ou par adresse IP, ainsi qu’au niveau global pour la totalité des requêtes. L’une des autres améliorations que nous avons implémentées portait sur la mise à l’échelle automatique. En s’appuyant sur un service à l’échelle de Meta qui prend en charge le scale-up et le scale-down des tâches, le nombre d’instances Gateway est désormais dynamique. Cela signifie qu’en situation de forte charge, le Gateway peut à présent faire l’objet d’un scale-up pour gérer le trafic supplémentaire et éviter d’atteindre sa limite en termes de CPU ou de mémoire, ce qui empêchera le scénario de blocage décrit ci-dessus. Combinée à la fonctionnalité de limitation des tentatives d’accès, cette possibilité garantit la fiabilité du Gateway, ainsi que sa capacité à supporter des schémas de trafic imprévisibles indésirables.
Figure 5 : Mise à l’échelle de l’architecture de Presto (diagramme conçu par Philip S. Bell)
Voici quelques aspects qu’il convient de garder à l’esprit lors du scale-up de Presto :
Cet article a été rédigé en collaboration avec Neerad Somanchi, ingénieur en production chez Meta, et Philip Bell, représentant des équipes de développement chez Meta.
Pour en savoir plus sur Presto, consultez le site prestodb.io, regardez une courte présentation de Presto par Philip Bell sur YouTube, ou suivez Presto sur Twitter, Facebook et LinkedIn.
Pour en savoir plus sur Meta Open Source, consultez notre site Open Source, abonnez-vous à notre chaîne YouTube, ou suivez-nous sur Twitter, Facebook et LinkedIn.