zookeeper実戦のサービス登録と発見

3685 ワード

zookeeper適用シーン
zk適用シーンを振り返る:
  • データ公開と購読
  • サービス登録と発見
  • 分散ロック
  • 分散キュー
  • マスター選挙
  • 配置センタ
  • ネーミングサービス
  • 負荷等化
  • zookeeperはサービス登録と発見を実現する
    サービスの登録と検出
    サービス登録と発見におけるzkの応用を見てみましょう.
    コード実装ロジック:
    サービス登録:
    public class ServiceRegister {
    
        private  static final String BASE_SERVICES = "/services";
        private static final String  SERVICE_NAME="/products";
    
        public static  void register(String address,int port) {
            try {
                ZooKeeper zooKeeper = new ZooKeeper("localhost:2181",5000,(watchedEvent)->{});
                Stat exists = zooKeeper.exists(BASE_SERVICES + SERVICE_NAME, false);
                if(exists==null) {
                    zooKeeper.create(BASE_SERVICES + SERVICE_NAME,"".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                }
                String server_path = address+":"+port;
                //          
                //              ,                         
                zooKeeper.create(BASE_SERVICES + SERVICE_NAME+"/child",server_path.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
                System.out.println("        ");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    検出サービス:
        public class InitListener implements ServletContextListener {
    
        private  static final String BASE_SERVICES = "/services";
        private static final String  SERVICE_NAME="/products";
    
        private ZooKeeper zooKeeper;
    
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            try {
                 zooKeeper = new ZooKeeper("localhost:2181",5000,(watchedEvent)->{
                    if(watchedEvent.getType() == Watcher.Event.EventType.NodeChildrenChanged  && watchedEvent.getPath().equals(BASE_SERVICES+SERVICE_NAME)) {
                        updateServiceList();
                    }
                });
    
                updateServiceList();
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        private void updateServiceList() {
           try{
               List children = zooKeeper.getChildren(BASE_SERVICES  + SERVICE_NAME, true);
               List newServerList = new ArrayList();
               for(String subNode:children) {
                   byte[] data = zooKeeper.getData(BASE_SERVICES  + SERVICE_NAME + "/" + subNode, false, null);
                   String host = new String(data, "utf-8");
                   System.out.println("host:"+host);
                   newServerList.add(host);
               }
               //       ip    ,    rpc  
               LoadBalance.SERVICE_LIST = newServerList;
           }catch (Exception e) {
               e.printStackTrace();
           }
        } 
    }
    
    public abstract class LoadBalance {
        public volatile static List SERVICE_LIST;
    
        public abstract String choseServiceHost();
    
    }
    
    /**
     *         
     */
    public class RamdomLoadBalance extends LoadBalance {
        @Override
        public String choseServiceHost() {
            String result = "";
            if(!CollectionUtils.isEmpty(SERVICE_LIST)) {
                int index = new Random().nextInt(SERVICE_LIST.size());
                result = SERVICE_LIST.get(index);
            }
            return result ;
        }
    }
    

    もういくつかのポイントを話します.サービスを登録するときは一時ノードを作成する必要があり、接続を切断するときはサービス側が掛けた後にノードを削除して監視できる2.サービスを登録するときに作成するのは順序ノードであり、一般的に同じサービスは何台かのマシンがあり、作成順序ノードは複数のマシンのサービスを区別することができる.検出サービスの一端は、サービスノードのサブノードをリスニングし、サブノードが削除されたり、新しいサブノードが作成されたり、サービスが利用可能なマシンを再検出したりします.
    dubboにおけるzkベースのサービス登録と発見もこの原理である