Java API 開発における分散調整のための ZooKeeper の使用

PHPz
リリース: 2023-06-17 22:37:44
オリジナル
1883 人が閲覧しました

コンピュータ システムのパフォーマンスが継続的に向上し、ハードウェア コストが継続的に削減されているため、現代のコンピューティングの分野では分散システムの重要性がますます高まっています。これに伴い、分散コンピューティングの需要は拡大し続けており、分散システムの調整および管理ソリューションの重要性が増しています。

分散調整を実現するソリューションは数多くありますが、ZooKeeper は人気のあるソリューションの 1 つです。 ZooKeeper は Apache Hadoop プロジェクトのサブプロジェクトの 1 つで、信頼性の高い分散調整サービスを提供し、アプリケーション開発者が分散システムを実装しやすくします。

Java API 開発における分散調整に ZooKeeper を使用することが話題になっています。この記事では、ZooKeeper の基本概念をいくつか説明し、Java での分散調整に ZooKeeper を使用する方法を説明する実践的な例を示します。

ZooKeeper の概要

ZooKeeper は、分散アプリケーションを調整するために設計された分散サービスです。 ZooKeeper の主な目的は、開発者がアプリケーションの作成に集中できるように、比較的シンプルな調整サービスを提供することです。

ZooKeeper には次の特徴があります。

  • ZooKeeper は、複数のノードを通じて展開して高可用性を提供できる分散サービスです。
  • ZooKeeper は、1 つのマスター ノードと複数のスレーブ ノードを備えたアーキテクチャとして設計されています。この構造では、マスター ノードはスレーブ ノードを調整および管理し、データが安全に保存されるようにする責任を負います。
  • ZooKeeper は、「ZooKeeper 一時順序付けノード」を使用してノードのステータスと変更を追跡します。これらのノードは、作成者と ZooKeeper サービスの間に 1 回限りの接続を確立する特別なタイプのノードです。接続が失われた場合、ノードは削除されるため、ノードのステータスが適時に更新されることが保証されます。
  • ZooKeeper はバージョン管理機能を使用してデータの一貫性と完全性を管理できます。バージョン管理を使用すると、ZooKeeper は各ノードのバージョン番号をインクリメントします。

ZooKeeper の基本操作

ZooKeeper を分散調整に使用する場合、最も一般的に使用される操作は、ノードの作成、ノードの読み取り、およびノー​​ドのステータスの監視です。

ノードの作成

ノードを作成するには、ノード パスとノード データを指定する必要があります。ノードは ZooKeeper サービスにサブディレクトリとして追加されます。作成されたノードが一時ノードの場合、そのノードを作成したクライアントと ZooKeeper サービスの間の接続が有効である限り、そのノードにアクセスできます。

以下は、ZooKeeper API を使用してノードを作成するためのサンプル コードです:

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);
ログイン後にコピー

ノードの読み取り

ZooKeeper を使用してノードの内容を読み取り、取得できます。 API。以下は、Java API を使用してノードを読み取るためのサンプル コードです。

ZooKeeper zk = new ZooKeeper("localhost:2181", 3000, null);
String nodePath = "/testNode";
byte[] data = zk.getData(nodePath, false, null);
ログイン後にコピー

ノードの監視

ノードを監視すると、クライアントにノードの変更が通知されるため、ノードのステータスを更新できます。以下は、ZooKeeper API を使用してノードを監視するためのサンプル コードです。

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);
ログイン後にコピー

分散調整に ZooKeeper を使用する例

次の例では、ZooKeeper API を使用して単純な分散アプリケーションを実装します。 、アプリケーションは、複数のプロセスがリーダーになるために競合する単純なリーダー選出プロトコルを実装します。この場合、ZooKeeper のエフェメラル ノードを使用してリーダー選出機能を実装します。

以下はサンプル コードです:

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();
       
   }
}
ログイン後にコピー

上記のサンプル コードでは、まず、リーダー選挙に参加するすべてのプロセスの参加ステータスを維持するために使用される znode サブディレクトリを作成します。次に、特定のアクターを表す一時的に順序付けされた ZooKeeper ノードを作成します。前に述べたように、ZooKeeper はクライアントと Zk 値の間に 1 回限りの接続を確立します。この一時ノードを作成した後、クライアント接続が失われると、ノードは削除されます。したがって、プロセスがノードの確立時に同じノード名のノードがすでに存在していることが判明した場合、そのプロセスはリーダーにはなりません。

クライアントが一時ノードの作成に成功すると、クライアントがリーダーになります。ここで、リーダーが実行するアクションを表す doLeaderAction() メソッドを呼び出すことができます。この例では、リーダーは 6 秒間の単純な操作を実行します。

クライアント接続が失われた場合、またはエラーが発生した場合、プロセスは既存のディレクトリの下のノードを検証し、どのノードが新しいリーダーになるかを決定します。

結論

分散調整と管理は、現代のコンピューティングの分野で最も重要な問題の 1 つであり、分散システムのアプリケーションはますます普及しています。 ZooKeeper は、開発者が分散システムを簡単に実装できるようにする人気のソリューションです。 Java API 開発では、分散調整に ZooKeeper を使用する主な操作には、ノードの作成、ノードの読み取り、ノードのステータスの監視が含まれます。この記事のサンプル コードを通じて、ZooKeeper を使用してリーダー選出プロトコルとその他の分散調整スキームを Java で実装する方法を確認できます。

以上がJava API 開発における分散調整のための ZooKeeper の使用の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート