Documentation¶
Guide du programeur¶
Version simulation (une seul JVM)¶
Pour notre implémentation de chord en java nous avons juste repris l'algorithme en pseudo langage qui nous était proposé en cours et nous l'avons adapté sans vraiment touché à l'algorithme lui-même. On retrouve donc une classe NodeImpl représentant un noeud de la chord qui contient toutes les fonctions utiles pour chord (stabilisation, ajout/retrait de noeud, ...).
Une instance de NoeudImpl représente un noeud, ce noeud garde une réference (au sens java) vers son prédécesseur et son successeur et une fingerTable (utile à l'algorithme) contenant elle aussi des références vers d'autres noeuds.
L'ID de chaque noeud devrait être le hash de son IP mais nous avons fait le choix ici d'attribuer un entier choisi par l'utilisateur au moment de la création du noeud pour simplifier l'utilisation de notre prototype et la compréhension des résultats obtenus.
Cet entier est compris entre 0 et 2^m avec m=7 définit dans le BootStrap.
Une fois le noeud créé un thread de stabilisation est lancé. Il se contente d'appeler les méthodes stabilize() et fixFingerTable() (cf algo du cours) régulièrement.
Un noeud propose aussi les méthodes addObject(int key, Object o) et getObject(int key), qui servent aux clients à utiliser cette DHT. Ces méthodes utilisent la méthode findSuccessor(int id) qui permet de trouver la place de l'objet dans la table.
Pour cette version nous avons aussi une classe BootStrap qui fourni à l'utilisateur une interface qui lui permet de créer une chord et d'observer au fur et à mesure l'évolution de cette chord.
L'utilisateur peut ainsi créer un noeud en lui attribuant un ID qui se joint automatiquement à la chord ou supprimer un noeud en indiquant juste son ID. Bootstrap contient en fait juste une référence vers le 1er noeud et utilise ses méthodes pour joindre ou supprimer un noeud.
BootStrap lance aussi un RMIregistry pour permettre à un client d'obtenir une référence vers le 1er noeud de la chord et ainsi s'en servir directement pour mettre et récupérer des objet dans la DHT en utilisant les méthodes addObject(int key, Object o) et getObject(int key) fournis par ce noeud (debut de la version RMI).
La classe Client à donc été créée pour tester les fonctionnalités de la DHT décrites ci-dessus.
Version RMI¶
La version RMI reprend exactement la même implémentation de l'algorithme que la précédente mais supprime complètement la notion de Bootstrap. Dans cette version un noeud peut se suffir à lui même, il constitue à lui tout seul une chord que l'on peut joindre à une autre chord déjà existante pour en former une nouvelle plus grande.
Chaque noeud et lancé dans sa propre JVM et possède maintenant son propre RMIregistry qu'un client peut utiliser pour se connecter et utiliser librement la DHT.
Toutes les références des noeuds entre eux sont maintenant des stubs et toutes les méthodes invoquées sont remotes. Il ne reste plus dans cette version que la classe NodeImpl, contenant un main qui cré un noeud avec la possibilité de le joindre à une chord et propose à tout moment de visualiser l'état de ce Noeud.
Guide de l'utilisateur¶
Test de la version RMI :¶
La version RMI de jchord permet de lancer plusieurs noeuds dans plusieurs JVMs
différentes. Il suffit ensuite de joindre les noeuds les uns aux autres pour former une chord. Dans cette version la classe de l'objet à ajouter dans la table doit être présente dans le Classpath de chaque noeud pour que l'objet puisse être désérialisé et stocké dans la table.
Deux fichiers jar ont été créés pour tester l'application prenant en compte les problèmes de Classpath. Cet exemple montre l'utilisation de jchord en réseau local avec le stockage d'objets « Sentences » créés pour l'occasion.
Pour commencer décompressez l'archive jchordRMI.zip et placez-vous dans le répertoire contenant les JARs (jchordRMI/bin/jar).
Puis dans un shell, lancer un premier noeud:
user@localhost $ ./java -jar node.jar
Un menu s'affiche et propose de créer une chord (avec un seul noeud au départ) ou de créer un noeud pour le joindre ensuite à une chord existante.
- Tapez 1 pour créer une nouvelle chord.
Il faut ensuite donner quelques informations pour créer le noeud. Commencez par renseigner les informations suivantes :Host : localhost Port : 8000 (par exemple)Le noeud est alors créé et constitue à lui tout seul une chord. A tout moment le menu propose d'afficher les informations du noeud (id, prédécesseur, successeur, figer table, objets présents dans la table)
Ensuite dans un nouveau shell, lancer une nouvelle fois node.jar.
- Tapez 2 pour créer un nouveau noeud et le joindre à la chord.
Renseignez comme précédemment :Host : localhost Port : 8001 (par exemple)Puis donnez les informations d'un noeud faisant déjà partie de la chord pour y joindre le nouveau noeud.Host : localhost Port : 8000 (numero du port du 1er noeud)
Nous avons maintenant une chord à 2 noeuds.
Cette opération peut être répétée autant de fois que nécessaire pour augmenter la taille de la chord.
Une fois la chord générée il ne reste plus qu'à lancer le client:
Dans un nouveau shell exécutez client.jar pour tester le fonctionnement.
user@localhost $ ./java -jar client.jar
Pour que le client puisse se servir de la chord il faut qu'il se connecte à un des noeuds. Commencez donc par donner l'adresse d'un noeud :
Host : localhost Port : 8000 (ou n'importe quel autre port d'un autre noeud)
Une fois le client connecté, il permet de tester les méthodes proposées par jchord:
- Tapez 1 pour ajouter un objet dans la chord:
Entrez un entier pour la clef compris entre 0 et 128, et un message (représentant l'objet « Sentence » à stocker). Par exemple :Key = 10 message = totoLe message est envoyé! Vous pouvez constater sa présence sur le noeud concerné par la clef que vous avez entré (cf l'algo) et affichant ses informations.
- Tapez ensuite 2 pour récupérer un objet, par exemple :
Key = 10 (la clef que vous avez choisi)Vous pouvez constater que vous avez bien récupéré l'objet.
Remarque: vous pouvez aussi effectuer les opérations addObject par un client et getObject par un autre client connecté à un autre noeud.
Bugs et Todo¶
La version RMI marche très bien en réseau local ou sur un cluster de machines
d'un même sous-réseau (comme le cluster eons de l'INRIA par exemple.). Mais il y a des problèmes si deux noeuds d'une même chord n'appartiennent pas au même réseau. Il faudrait s'intéresser de plus près aux fonctionnement de RMI.
Dans la version de simulation nous avons géré la déconnection d'un noeud de
manière « propre », c'est à dire si on utilise les méthodes de déconnections du noeud qui préviennent l'ensemble de la chord de la déconnection. Mais il n'y a aucune gestion de déconnection si on tue le thread d'un noeud.
Dans la version RMI aucune déconnection de noeud n'est gérée.
Pour les deux versions les interfaces sont très peu robustes aux erreurs de
syntaxe lors de la saisie des données.
Pour la version RMI on est obligé d'ajouter au classpath des noeuds les classes
des objets que souhaite enregistrer dans la DHT. Il faudrait mettre au point un protocole entre le client et la DHT pour gérer ce problème: la DHT n'est pas obligée de connaître la classe de l'objet à stocker, elle pourrait se contenter d'enregistrer une donnée correspondant à une sérialisation spécifique à notre protocole de l'objet faite par le client avant de l'envoyer. Ce même client pourrai ensuite faire le travail inverse lorsqu'il récupère cette donnée pour désérialiser et reconstruire l'objet.