J’ai lancé depuis quelques temps un projet dans mon entreprise, que nous venons de publier sous licence libre. Il s’agit d’un système de fichiers répliqué du nom de FineFS.
Je vais en parler ici parce qu’il s’agit d’un projet intéressant d’un point de vue technique, sur lequel les esprits imaginatifs peuvent venir s’éclater avec nous. Mais aussi parce qu’à travers ce projet, je veux vous présenter l’univers des systèmes répartis/distribués/redondés et des bases de données à très haute disponibilité – que tout directeur technique doit connaître un minimum.
Présentation du projet
Le but de ce projet est de faciliter la création de cluster-disque. Lorsque vous avez plusieurs serveurs qui doivent accéder aux mêmes fichiers, il est toujours délicat de mettre en place une architecture satisfaisante sans dépenser des sommes folles. Et pourtant, la moindre infrastructure Web présente plusieurs serveurs frontaux, qui doivent délivrer des contenus (images, vidéos, musiques) communs. Sans compter que ces différents serveurs doivent aussi pouvoir enregistrer de nouveaux fichiers, qui doivent être accessibles à toutes les autres machines.
Il existe plusieurs moyens de mettre des fichiers à dispositions de plusieurs serveurs :
- Installer un NAS, c’est-à-dire un serveur de fichiers. Mais si ce serveur tombe en panne, plus aucun fichier n’est accessible.
- Installer un SAN, qui prend souvent la forme d’une baie de stockage redondée. Mais les prix de ce genre d’installation grimpent très vite.
- Utiliser un service externe, comme Amazon S3, qui prend en charge les aspects complexes de la gestion des fichiers. C’est souvent une solution satisfaisante pour du Web, mais qui peut induire des latences dans les accès aux fichiers, et des coûts inutiles.
- Mettre en place un système de fichiers réparti, redondé et/ou distribué.
C’est dans cette dernière catégorie que se place FineFS. Il existe déjà des solutions qui s’emploient à résoudre ce besoin, qu’on peut répartir en 5 groupes :
- Les systèmes basés sur le modèle des bases de données : Dynamo, Cassandra, …
- Les systèmes utilisant un serveur centralisé : MooseFS, Lustre, DRBD, Chirp, GfarmFS, …
- Ceux basés sur l’exploitation d’un SAN : GFS, OpenGFS, QFS, GPFS, OCFS, …
- Ceux qui ne sont pas des vrais systèmes répartis mais peuvent remplir le même genre d’usages : Peerfuse, ChironFS, PersistentFS (basé sur S3), MogileFS, …
- Les systèmes de fichier distribués et/ou répartis : GlusterFS, ZFS, POHMELFS, Cloudstore, Ceph, Coda, …
La plupart présentent toutefois des inconvénients majeurs par rapports à nos besoins qui sont sommes toute assez simples. Soit les fonctionnalités ne sont pas celles qu’on attend, soit le coût d’installation ou de maintenance semble exagéré.
Choix techniques
La philosophie initiale de FineFS se rapproche un peu de celle de MogileFS. Ce n’est pas un système de fichiers au sens habituel du terme (comprendre compatible POSIX), mais une infrastructure logicielle qui permet de partager des fichiers entre plusieurs machines. Par contre, la réalisation technique est complètement différente.
Quelques contraintes ont guidé les choix techniques :
- La lecture de fichiers doit être la plus rapide possible => on recopie les fichiers en local sur tous les serveurs.
- La cohérence des données est importante, mais sans contrainte de temps réel => on utilise le paradigme de l’eventual consistency.
- Le système doit être simple et rapide à développer et bien s’intégrer dans un environnement orienté Web => le fonctionnement repose sur des outils standards, stables et connus (xinetd, crontab), le développement est fait en PHP.
La réalisation technique est en partie inspirée des principes de Dynamo et Cassandra, des bases de données créées respectivement par Amazon et Facebook.
Pour faire simple, les serveurs (ou « noeuds ») d’un cluster sont placés dans une boucle au sein de laquelle chaque serveur réplique ses données vers le serveur suivant. Mais le danger est alors qu’un fichier un peu gros prenne beaucoup de temps à faire le tour de la boucle. C’est pour cela que nous avons mis en place une stratégie de réplication en 2 temps :
- Dès la création (ou la mise-à-jour, l’effacement, le renommage) d’un fichier, un petit message fait les tour du cluster pour prévenir rapidement tous les noeuds.
- De manière asynchrone, un programme s’exécute sur chaque noeud, pour copier vers le noeud suivant le contenu des nouveau fichiers.
Pour en savoir plus
Je vous conseille d’aller jeter un oeil sur les liens suivants :
- Le site du projet, hébergé sur Google Code.
- Le groupe de discussion consacré aux logiciels libres de FineMedia.
- L’annonce sur LinuxFR, dans laquelle vous pourrez trouver des échanges de commentaires assez intéressants.
N’hésitez pas à participer, soit sur le groupe de discussion, soit en testant le logiciel, soit en proposant des amélioration de code.
Et si vous cherchez un poste intéressant en développement web, au sein duquel vous aurez des responsabilité sur FineFS, contactez moi ! 😉
Et le futur ?
Nous avons de nombreuses idées d’améliorations pour FineFS. Nous n’en sommes qu’aux prémisses de ce projet. Pour commencer, nous allons travailler sur la souplesse d’administration, pour faciliter l’ajout de noeuds à un cluster, ou la création de passerelles entre les clusters. Ensuite, nous allons permettre l’utilisation de noeuds « partiels », qui ne contiennent pas l’intégralité des données du cluster, mais qui gardent en cache les fichiers les plus demandés.
Une des pistes d’amélioration les plus intéressantes sera la possibilité de rechercher des fichiers à partir de leurs méta-données et non pas uniquement par leur nom. Les fichiers peuvent déjà comporter des méta-données, des informations textuelles simples sous forme de paires clé-valeur. Permettre de de faire des recherches sur ces données permettrait de se passer de bases de données relationnelles dans certains cas, ce qui pourrait accélerer les applications. À ce sujet, je vous suggère d’aller lire l’article Is the relational database doomed. Il présente assez bien pourquoi les bases de données non relationnelles reviennent à la mode, principalement sur les grosses architectures Web de « cloud-computing ».
Comme il est dit dans beaucoup de commentaire sur LinuxFR, il s’agit surtout d’une librairie plus que d’un système de fichier ?
Pour que votre outil soit largement utilisé, il faudrait développer des plugins pour les principaux CMS, et surtout Drupal qui se veux être utilisé pour de grand projet.
En tout cas, il s’agit d’une bonne initiative. Féliciation.
Non, ce n’est pas simplement une librairie ! Il y a un démon qui tourne sur chaque nœud du cluster (pour gérer les échanges de données entre les nœuds et depuis l’extérieur du cluster), et des processus de réplication des données entre les noeuds.
Ce n’est pas un filesystem au sens POSIX du terme. Mais ça l’est tout autant que MogileFS, par exemple.
Je ne comprend pas un truc: pourquoi est ce que ca réplique vers le noeud suivant?
Et si celui ci tombe, la boucle s’interromps?
Pourquoi est ce que cela ne recopie pas vers un noeud au hasard ne disposant pas du fichier?
C’est assez bien expliqué (avec des images 😉 ) sur le site du projet.
Pour simplifier, disons que le but du jeu est d’avoir les données en local sur tous les serveurs. Ainsi, quand un nouveau fichier est créé sur un serveur, il le transmet à la machine suivante, et ainsi de suite jusqu’à ce que ça ait fait le tour complet.
Si jamais une machine (vers laquelle un serveur tente de « pousser » un fichier) est en panne, ce n’est pas grave, le serveur transmet le fichier à la machine qui était juste après dans la boucle.
Si c’est la machine dont c’était le tour de répliquer qui tombe en panne, c’est un peu plus compliqué. La réplication est alors stoppée. Mais lorsqu’un autre serveur aura besoin du fichier, il ira le chercher auprès du serveur d’origine du fichier (ou un autre serveur qui suivait dans la boucle), puis le répliquera vers la suite du cluster.
Bonjour (désolé de relancer le thread)
J’ai parcouru un peu le code, qui ‘ l’avantae d’etre simple et court et qui répond bien a une propblématique web
Cependant, la gestion des erreurs me semble un peu légere.
Que se passe t’il si un des serveurs de la boucle tombe ? j’ai bien vu que le fichier etait répliqué sur les autres, mais pas de reprises sur erreur lorqu’il remonte ? (un rsycn dans le script de demarraghe autrait peut etre fait l’affaire ?)
de meme, tte la gestion des erreurs lorsque le disque est plein, ou la machine est trop chargés pour un tps x etc (meme si on considere que chaque serveur doit avoir la meme conf et donc la meme taille de disque, on peut t de meme avoir des serveurs heterogenes et avec des tailles de disques différents)
D’ailleurs, plutot qu’un jeton qui tourne sur la boucle pour signaler la presence d’un fichier, pkoi ne pas avoir fait en sorte qu’un serveur qui ecrit un fichier informe tt les serveurs du noeud ? ca aurait été plus simple a gerer non ? (et aussi efficace : n connexion a realiser dans les deux cas, avec n=nb de serveurs ?)
Coté securité c’est un peu limite aussi, un file systeme peut qd meme etre trés vite corrompu si on ne fait pas bien attention a ses regles au niveau des firewall.. (si on en a un, sinon, vive ip tables 😉 )
on va encore etudier un peu le code.. merci en tout cas de la difffusion !
Pas de soucis de relancer le thread, je suis toujours content de répondre aux questions sur FineFS.
Il y a bien un système de reprise sur erreur, contrairement à ce que tu as cru voir (c’est pourtant expliqué dans la page d’architecture du projet). Si un serveur tombe en panne, le serveur précédent du cluster (qui n’arrivera pas à s’y connecter) enregistre dans un fichier de log chaque information qu’il n’aura pas pu transmettre. Il les transmettra au serveur d’après dans la boucle. Lorsque le serveur en panne réintègre le cluster, le serveur précédent dans la boucle lui enverra toutes les informations qu’il aura manqué, lui permettant de rattraper son retard.
Il n’y a pas de gestion de l’espace disque au niveau du cluster entier. Si on essaye d’écrire un fichier et qu’il n’y a pas assez d’espace en local, le système lève une exception. Et comme on part du principe que tous les nœuds actifs du cluster doivent pouvoir contenir toutes les données stockées, tout se passe bien.
Je reste sceptique sur la capacité des autres systèmes de fichiers distribués à pouvoir gérer cela efficacement sans avoir un serveur centralisé qui constituerait un « single point of failure ».
Du point de vue de la sécurité, le postulat de départ est l’exécution dans un environnement non hostile. Pas de gestion de droits utilisateurs, pas de login/password, pas d’encryption des données. Tout cela simplifie grandement l’implémentation, et assure des performances maximales.
Ça ne sert à rien de vouloir coder soi-même ce qu’on peut gérer bien plus efficacement avec un firewall et éventuellement un VPN.
Enfin, la remarque sur le jeton versus contacter directement tous les autres serveurs… Il suffit de prendre 10 minutes pour réfléchir concrètement à l’implémentation d’un tel système, pour se rendre compte que la mise en boucle des serveurs est à la fois plus simple (dans le traitement des erreurs, par exemple), plus efficace (au final, la communication circule au moins aussi vite) et plus robuste (le risque de perte de données est moindre).
Merci pour la réponse.
J’avoue avoir parcouru le code en 15 min, je suis surement passé a coté de choses effectivement, et aurais du plus regarder avant de poster 😉
Je ne critique absolument pas le systeme, qui comme je l’ai dit, est en effet adapté a ce qu’on lui demande. (je rebondi qques remarques dans les forums qui le critique… qd on achete une moto, on lui demande pas d’avoir un coffre, qd on choisit un soft, on le choisi en adéquation a son besoin 😉 Donc non, ce n’est pas FS, mais oui, il répond a une problématique répandue dans la gestion de load balancing web…)
Pour tout dire, j’allais me lancer dans un soft +/- équivalent, sauf que :
je prévoyais vraiment un serveur centralisé (ou du moins « maitre ») qui permet d’avoir l’exhaustivité des fichiers et sur lequel on peut avoir « confiance ».
Dans FineFS, j’ai tt de meme l’impression qu’on peut arriver a une desynchronisation en cas de coupures etc (les causes peuvent etre multiples et suivant les cas, on peut imaginer qu’un fichier ne soit pas recopié sur un disque.. dans ce cas la, on aura bien du mal a reconstruire la meme arborescence sur tt les serveurs, puisqu’on ne pourra pas savoir qui a ou pas les bons fichiers) Les autres systemes qui utilisent une BDD le font d’ailleurs en gde partir pour ca…
Et c’est tjs emebetant, dans la gestion d’image sutilisateurs de dire « on a perdu votre image » (meme si on leur dit pas vraiment 😉 )
Enfin, y’a un autre point que je cherche a réglé qui ne l’est pas dans fineFS (et tu le dis bien toi meme) c’est l’assurance, que lorsqu’on demande un fichier, si il a été copié qqpart, de le retrouver sur n’importe quel frontal. dans le cas de fineFS, si le token a pas eu le tps de faire le tour de la boucle, le serveur répond que le fichier n’existe pas. (j’expliquerais, pkoi dns certains cas pour moi c’est génant). L’argument de dire « la boucle est vite bouclée » est vrai, mais ttes personnes qui gerent un peu de traffic sur un site sait qu’un jour ou l’autre, un des frontaux peut avoir de la charge pour une raison x ou y, qu’il peut mettre du temps a ouvrir la connexion vers son voisin etc, et que je pense qu’on peut avoir qques secondes (voir plus avec les timeout de connexion entre deux serveurs) dans certains cas pour boucler la boucle…
Dans mon cas, les utilisateurs postent des images, et peuvent les modifier (les recadrer, les flouter, etc etc). Lors d’une telle opération, le serveur frontal (ou plutot « un des serveurs » ) applique le traitement et renvoi une réponse au client une fois le traitement terminé. ce qui a pour effet que le nav du client recharge l’image transformée. seulement, si il la recharge avant que l’info ait fait le tour de la boucle, dommage, il aura l’image d’origine… et c’est pour ca que je voyais un serveur maitre qui a tjs l’exaustivité de l’info.
dans ce que je pensais, lorqu’on faisait un « put » d’un fichier dans le systeme, le serveur centralisé invalidait le cache pour le fichier sur tt les esclaves, et renvoyait la réponse comme quoi l’opération PUT etait ok seuelemnt qd tt les esclaves avait bien effacé leur cache (la aussi, il y a une gestion d’erreurs a faire qui n’est pas évidente).
Dans ton cas, il faudrait attendre que le jeton ai bien fini sa boucle pour valider la copie du fichier dans le FS et pouvoir aussurer que les images délivrées seront bien les plus a jour.
bref, je pense qu’on est confronté a des questions que tu t’es deja posé, avec efffectivement le pb du serveur centralisé pour nous, qui est single point of failure pour les MAJ de fichier (les read seraient ok, puisque les frontaux auraient leur cache en local), ce qui est evidemment une grosse lacune. (l’idée etant peut etre de changer dynamiquement le serveur maitre, mais ca pose plein de pb aussi pour informer les autre sfrontaux en tps réel etc… et avoir une serveur frontal qui fait un job différent des autres, c’est tjs embetant, et j'(on) aime pas 😉 )
et juste une rq (je cite) : Il suffit de prendre 10 minutes pour réfléchir concrètement à l’implémentation d’un tel système, pour se rendre compte que la mise en boucle des serveurs est à la fois plus simple (dans le traitement des erreurs, par exemple), plus efficace (au final, la communication circule au moins aussi vite) et plus robuste
Pas si convaincu que ca… je pense que les problématiques sont gérés un peu différement, mais sont bien les memes. et que la compexité au final est peut etre la meme. dans la boucle, si on reflechit un peu, si on a deux serveurs qui se suivent dans la boucle qui tombe l’un apres l’autre, que le premier qui est tombé remonte avant le deuxieme, je pense qu’on perd de l’info… mais j’ai réfléchi a ca que 2 min 😉 )
ah oui, une derniere chose… considerer, que qd on gere un web avec un peu de traffic, on n’est pas dans un milieu hostile, ca me semble un peu antinomique 😉
(j’ai bien compris que tu parlais d’etre sur un VLAN avec firewall / proxy etc, mais bon.. la phrase en elle meme m’a fait réagir. sauf si on parle d’un intranet sans connexions exeternes, mais je crois que ca existe plus 😉 )
un postulat de base pour moi est : « nous sommes dans un milieu hostile »
Cette discussion est intéressante. Elle aurait bien sa place sur le forum de discussion de FineFS 😉
Le serveur centralisé est effectivement une solution plus facile à implémenter. Mais si le serveur centralisé tombe, c’est le cluster entier qui est inutilisable. Et redonder ce serveur centralisé est une question aussi complexe que pour l’ensemble du cluster.
Pour moi, la voie du « totalement décentralisé » était une évidence. Mais si tu t’intéresse aux systèmes avec serveur centralisé, tu peux regarder du côté de HDFS, GfarmFS, Chirp, Ceph, Tahoe-LAFS, MooseFS ou MogileFS.
Sinon, FineFS est basé sur l’eventual consistency. Il existe une probabilité qu’un nœud du cluster ne sache pas encore qu’une nouvelle version d’un fichier est disponible. Mais en pratique ce n’est pas un problème pour 2 raisons :
– C’est le fichier de méta-données qui doit faire le tour du cluster à toute vitesse. Sauf cas particulier, ce fichier fait à peine quelques centaines d’octets.
– Quoi qu’on en dise, les applications Web n’ont pas besoin de « temps réel ».
Dans le cas d’une application qui traite des images, comme tu le dis, il faut de toute manière un affichage asynchrone. Pendant que l’image est redimensionnée, tu affiches un message d’attente à l’utilisateur, et la page se recharge régulièrement pour voir si le statut à changé. Une fois le traitement terminé, il y a de grandes chances que les serveurs soient avertis avant l’utilisateur de la présence du nouveau fichier.
Habituellement, un utilisateur tombera sur le même serveur frontal pendant une certaine durée (que ce soit par la gestion des sessions d’un load-balancer, ou par DNS round robin). Donc dans le cas d’un cluster FineFS dont les données sont redondées directement surl les frontaux, l’internaute ne verra pas de latence.