Maison  >  Article  >  Java  >  Utilisation de ZooKeeper pour la coordination distribuée dans le développement d'API Java

Utilisation de ZooKeeper pour la coordination distribuée dans le développement d'API Java

PHPz
PHPzoriginal
2023-06-17 22:37:441882parcourir

Avec l'amélioration continue des performances des systèmes informatiques et la réduction continue des coûts matériels, les systèmes distribués deviennent de plus en plus importants dans le domaine de l'informatique moderne. Parallèlement, la demande en informatique distribuée continue de croître et les solutions de coordination et de gestion des systèmes distribués deviennent de plus en plus importantes.

Il existe de nombreuses solutions pour réaliser une coordination distribuée, et ZooKeeper est l'une des solutions les plus populaires. ZooKeeper est l'un des sous-projets du projet Apache Hadoop. Il fournit un service de coordination distribué fiable, facilitant la mise en œuvre de systèmes distribués par les développeurs d'applications.

L'utilisation de ZooKeeper pour la coordination distribuée dans le développement d'API Java est devenue un sujet brûlant. Cet article explorera quelques concepts de base de ZooKeeper et fournira des exemples pratiques pour illustrer comment utiliser ZooKeeper pour la coordination distribuée en Java.

Introduction à ZooKeeper

ZooKeeper est un service distribué conçu pour coordonner les applications distribuées. L'objectif principal de ZooKeeper est de fournir aux développeurs un service de coordination relativement simple afin qu'ils puissent se concentrer sur l'écriture d'applications.

ZooKeeper présente les fonctionnalités suivantes :

  • ZooKeeper est un service distribué qui peut être déployé via plusieurs nœuds pour fournir une haute disponibilité.
  • ZooKeeper est conçu comme une architecture avec un nœud maître et plusieurs nœuds esclaves. Dans cette structure, le nœud maître est chargé de coordonner et de gérer les nœuds esclaves et de garantir que les données sont stockées en toute sécurité.
  • ZooKeeper suit l'état et les modifications des nœuds en utilisant "ZooKeeper Temporary Ordered Nodes". Ces nœuds sont un type spécial de nœud qui établit une connexion unique entre leur créateur et le service ZooKeeper. Si la connexion est perdue, le nœud sera supprimé, garantissant ainsi que l'état du nœud est mis à jour en temps opportun.
  • ZooKeeper peut gérer la cohérence et l'intégrité des données en utilisant la fonction de contrôle de version. Lors de l'utilisation du contrôle de version, ZooKeeper incrémentera le numéro de version de chaque nœud.

Opérations de base de ZooKeeper

Lors de l'utilisation de ZooKeeper pour la coordination distribuée, les opérations les plus couramment utilisées sont la création de nœuds, la lecture de nœuds et la surveillance de l'état des nœuds.

Créer un nœud

Pour créer un nœud, vous devez fournir le chemin du nœud et les données du nœud. Le nœud sera ajouté au service ZooKeeper en tant que sous-répertoire. Si le nœud créé est un nœud éphémère, il n'est accessible que tant que la connexion entre le client qui l'a créé et le service ZooKeeper est valide.

Ce qui suit est un exemple de code pour créer un nœud à l'aide de l'API ZooKeeper :

ZooKeeper zk = new ZooKeeper("localhost:2181", 3000, null);
String nodePath = "/testNode";
byte[] data = "nodeData".getBytes();
CreateMode createMode = CreateMode.EPHEMERAL;
zk.create(nodePath, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, createMode);

Lecture d'un nœud

Vous pouvez lire et obtenir le contenu d'un nœud en utilisant l'API ZooKeeper. Voici un exemple de code pour lire les nœuds à l'aide de l'API Java :

ZooKeeper zk = new ZooKeeper("localhost:2181", 3000, null);
String nodePath = "/testNode";
byte[] data = zk.getData(nodePath, false, null);

Surveillance des nœuds

La surveillance des nœuds permet au client d'être informé des modifications des nœuds, afin que l'état du nœud puisse être mis à jour. Voici un exemple de code pour surveiller les nœuds à l'aide de l'API ZooKeeper :

ZooKeeper zk = new ZooKeeper("localhost:2181", 3000, null);
String nodePath = "/testNode";
Watcher watcher = new Watcher() {
   public void process(WatchedEvent event) {
      // do something
   }
};
byte[] data = zk.getData(nodePath, watcher, null);

Exemple de coordination distribuée utilisant ZooKeeper

Dans l'exemple suivant, nous implémenterons une application distribuée simple à l'aide de l'API ZooKeeper, qui implémentera un simple protocole d'élection de leader où plusieurs processus seront en compétition pour devenir le leader. Dans ce cas, nous utiliserons les nœuds éphémères ZooKeeper pour implémenter la fonction d'élection des leaders.

Voici l'exemple de code :

import java.util.List;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.KeeperException.NodeExistsException;
import org.apache.zookeeper.data.Stat;
 
public class LeaderElection implements Watcher {
    
   String znode = "/leader_election";    

   ZooKeeper zk;
   String serverId = Integer.toHexString((int)(Math.random() * 1000000));
    
   boolean isLeader = false;
    
   public void start() throws Exception{
       
      String serverPath = znode + "/" + serverId;
 
      zk = new ZooKeeper("localhost:2181", 3000, this); 

      while(zk.getState() == ZooKeeper.States.CONNECTING){
         
         Thread.sleep(500); 

      }
       
      while(true){
          
        try{
        
            // create the node with EPHEMERAL and SEQUENTIAL flags
            
            zk.create(serverPath, null, ZooDefs.Ids.OPEN_ACL_UNSAFE,
              CreateMode.EPHEMERAL);
          
            isLeader = true; 

            doLeaderAction();
            break;

         } catch (NodeExistsException e){
                
            isLeader = false;
            break; 

         } catch (InterruptedException e) {
             
             throw e;
             
         } catch (Exception e) {
             
             throw new RuntimeException(e); 
             
         }
      }
   }
    
   public void stop() throws Exception{
       
      zk.close(); 
       
   }
   
   void doLeaderAction() throws Exception {
       
      System.out.println("Becoming leader: " + serverId);
       
      try {            
               
         Thread.sleep(6000);
               
      } catch (InterruptedException e) {

         System.err.println("Interrupted while " +
               "sleeping during leadership.");
         
         Thread.currentThread().interrupt();
      } finally {

         try {               
            System.out.println("Ending leader: " + serverId);
         } catch (Exception e) {
            System.err.println("Error ending leadership."); 
         }
      }
   }
    
   public void process(WatchedEvent e){
       
      System.out.println(e.toString() + ", " + serverId);
      try {
        electLeader();
      } catch (Exception ex) {
        ex.printStackTrace();
      }   
   }
    
   void electLeader() throws Exception {
       
      Stat predecessorStat = null;
      String predecessor = null;
      
      List<String> children = zk.getChildren(znode, false); //(watcher not needed for this operation)
      
      int currentId = Integer.parseInt(serverId, 16); 
       
      for(String child : children){
          
        int childId = Integer.parseInt(child, 16);
        
        if(childId < currentId) {
            
            if(predecessorStat == null){
                
                predecessor = child; 
                predecessorStat = zk.exists(znode + "/" + child, true); 

            } else {
                
                Stat stat = zk.exists(znode + "/" + child, true);
              
                if(stat.getMzxid() < predecessorStat.getMzxid()){
                    
                    predecessor = child; 
                    predecessorStat = stat; 
                }               
            }
        }

      }
       
      if(predecessor == null){
           
        System.out.println("No active group members, " + serverId + " as leader.");
        //...provisional leader code here
           
      } else{ // watch the predecessor node waiting for it to go
                // ...down or to receive a message that it is was elected leader too.        
        System.out.println("Watching group member with higher ID: " + predecessor);
      }         
   }
   
   public static void main(String[] args) throws Exception {
          
      LeaderElection election = new LeaderElection();
      
      election.start();
       
   }
}

Dans l'exemple de code ci-dessus, nous créons d'abord un sous-répertoire znode qui conserve l'état de participation de tous les processus participant à l'élection du leader. Ensuite, nous créons un nœud ZooKeeper ordonné temporaire qui représente un acteur donné. Comme mentionné précédemment, ZooKeeper établit une connexion unique entre le client et la valeur Zk. Après avoir créé ce nœud temporaire, si la connexion client est perdue, le nœud sera supprimé. Par conséquent, si un processus découvre qu'un nœud portant le même nom de nœud existe déjà lors de l'établissement d'un nœud, le processus ne deviendra pas le leader.

Si le client crée avec succès le nœud temporaire, le client deviendra le leader. Ici, nous pouvons appeler la méthode doLeaderAction() qui représente l'action que le leader effectuera. Dans cet exemple, le leader effectuera une opération simple de 6 secondes.

Si la connexion client a été perdue ou qu'une erreur se produit, le processus vérifie les nœuds sous le répertoire existant pour déterminer lequel devient le nouveau leader.

Conclusion

La coordination et la gestion distribuées sont l'une des questions les plus importantes dans le domaine de l'informatique moderne, et l'application de systèmes distribués devient de plus en plus populaire. ZooKeeper est une solution populaire qui facilite la mise en œuvre de systèmes distribués par les développeurs. Dans le développement de l'API Java, les principales opérations d'utilisation de ZooKeeper pour la coordination distribuée incluent la création de nœuds, la lecture des nœuds et la surveillance de l'état des nœuds. Grâce à l'exemple de code de cet article, vous pouvez voir comment utiliser ZooKeeper pour implémenter le protocole d'élection des dirigeants et d'autres schémas de coordination distribués en Java.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn