1. 程式人生 > 其它 >Zookeeper實現服務註冊與發現

Zookeeper實現服務註冊與發現

在分散式架構中,系統經常被暴漏為服務供其他系統呼叫,為使系統間能夠相互通訊,需要有一個協調系統來管理這些服務,這就是服務註冊與服務發現,這個協調者也被稱之為註冊中心。
下面基於zookeeper來實現一個簡單的服務註冊與發現功能

通過Maven引入需要的jar包

<dependency>
  <groupId>com.101tec</groupId>
  <artifactId>zkclient</artifactId>
  <version>0.11</version>
</dependency>

建立服務註冊類

package com.wrxiang.zk.util;

import org.I0Itec.zkclient.ZkClient;

public class ZkServiceRegistry {

    private ZkClient zkClient;

    public void registry(String serviceName, String serviceAddress){

        zkClient = new ZkClient("127.0.0.1");

        //建立registry節點
        String registryAddress = "/services";
        if(!zkClient.exists(registryAddress)){
            zkClient.createPersistent(registryAddress);
            System.out.println("建立服務註冊節點");
        }

        //建立service節點
        String servicePath = registryAddress + "/" + serviceName;
        if(!zkClient.exists(servicePath)){
            zkClient.createPersistent(servicePath);
            System.out.println("建立服務節點,服務名:" + serviceName);
        }

        //建立address節點(臨時)
        String addressPath = servicePath + "/address-";
        String addressNode = zkClient.createEphemeralSequential(addressPath, serviceAddress);
        System.out.println("建立服務地址節點:" + addressNode);
    }
}

建立服務發現類

package com.wrxiang.zk.util;

import org.I0Itec.zkclient.ZkClient;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ThreadLocalRandom;

public class ZkServiceDiscovery {

    private final List<String> addressCache = new CopyOnWriteArrayList<>();

    private ZkClient zkClient;

    public String discovery(String serviceName){

        zkClient= new ZkClient("127.0.0.1");

        String servicePath =  "/services/" + serviceName;
        if(!zkClient.exists(servicePath)){
            throw new RuntimeException("未發現服務節點:" + servicePath);
        }

        String address;

        //先從本地系統快取中取
        if(addressCache.size() == 1){
            address = addressCache.get(0);
        }else if(addressCache.size() > 1){
            address = addressCache.get(ThreadLocalRandom.current().nextInt(addressCache.size()));
        }else{
            //從ZK註冊中心中取
            List<String> addressList = zkClient.getChildren(servicePath);
            addressCache.clear();
            addressCache.addAll(addressList);

            zkClient.subscribeChildChanges(servicePath,(parentPath,currentChilds)->{
                System.out.println("監聽服務節點發生變化:" + parentPath);
                addressCache.clear();
                addressCache.addAll(currentChilds);
            });

            if(CollectionUtils.isEmpty(addressCache)){
                throw new RuntimeException("未發現有效的服務節點");
            }

            if(addressList.size() == 1){
                address = addressList.get(0);
            }else {
                address = addressList.get(ThreadLocalRandom.current().nextInt(addressList.size()));
            }
        }

        //獲取實際地址
        String addressPath = servicePath + "/" + address;
        String hostAndPort = zkClient.readData(addressPath);

        System.out.println("獲取到實際訪問地址:" + hostAndPort);
        zkClient.close();
        return hostAndPort;
    }
}

建立測試類

package com.wrxiang.zk.util;

public class ZookeeperApplicationTest {

    public static void main(String[] args) throws InterruptedException {

        String serviceName = "test.com";

        ZkServiceRegistry registry = new ZkServiceRegistry();
        registry.registry(serviceName,"192.168.3.1:8080");

        Thread.sleep(1000);

        ZkServiceDiscovery zkServiceDiscovery = new ZkServiceDiscovery();
        zkServiceDiscovery.discovery(serviceName);

    }
}

啟動zookeeper,然後執行測試類,可以發現服務能夠正常註冊到zookeeper,也能夠被正常的發現。

本文來自部落格園,作者:風煙景,轉載請註明原文連結:https://www.cnblogs.com/wrxiang/p/15145389.html