1. 程式人生 > >Zookeeper 配置中心服務治理實現

Zookeeper 配置中心服務治理實現

Zookeeper配置中心服務治理實現

背景

上一篇部落格詳細講解了為什麼我們要選擇Zookeeper作為服務發現框架而不是使用Eureka。
參考 這篇部落格將繼續講解怎麼實現的,裡面會有大量的程式碼的拷貝,具體的架構可以參考上一篇部落格的架構演進圖。本篇主要講解實現過程。

準備工作

  1. Spring Maven專案新增Zookeeper的依賴包,這樣就可以使用Zookeeper的SDK了。
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId> <version>3.3.6</version> </dependency>

football-server實現服務註冊功能

建立Zookeeper.properties在resources目錄下,並寫入引數。

server.parent.name = football (註冊服務的父路徑)
server.instance.name = football-server (註冊服務的名字)
server.port
= 8081 (註冊服務的埠號) zookeeper.host = Your zookeeper address zookeeper.port = Your zookeeper port

建立Zookeeper.properties讀取檔案的類。

@Component
public class ZookeeperProperties {

    @Value("${zookeeper.host}")
    private String host;

    @Value("${zookeeper.port}")
    private String zkPort;

    @Value
("${server.parent.name}") private String parentName; @Value("${server.port}") private String serverPort; @Value("${server.instance.name}") private String instanceName; public String getZookeeperAddress(){ return String.format("%s:%s",host,zkPort); } public String getParentName() { parentName=parentName.replace("/",""); return parentName; } public String getServerPort() { return serverPort; } public String getInstanceName() { parentName=parentName.replace("/",""); return instanceName; } }

在服務啟動成功後,呼叫Zookeeper的JavaSDK向Zookeeper註冊自己。


@Service
public class ZookeeperRegistrar implements ApplicationListener<ContextRefreshedEvent> {


    @Autowired
    ZookeeperProperties zookeeperProperties;



    private static Logger log = LoggerFactory.getLogger(ZookeeperRegistrar.class);


    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        if(contextRefreshedEvent.getApplicationContext().getParent()==null){
            try {
                registry();
            } catch (IOException e) {
                log.error("fooball-server registry to zookeeper fault ,{}",e.getMessage());
                e.printStackTrace();
            } catch (InterruptedException e) {
                log.error("fooball-server registry to zookeeper fault ,{}",e.getMessage());
                e.printStackTrace();
            } catch (KeeperException e) {
                log.error("fooball-server registry to zookeeper fault ,{}",e.getMessage());
                e.printStackTrace();
            }

        }
    }

    public void registry() throws IOException, KeeperException, InterruptedException {

        Watcher watcher=new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                log.info("zookeeper watcher ,{}",watchedEvent.toString());
            }
        };
        ZooKeeper zooKeeper = new ZooKeeper(zookeeperProperties.getZookeeperAddress(),200000,watcher);
        initParentPath(zooKeeper,watcher);
        createInstancePath(zooKeeper,watcher);

    }

    public void initParentPath(ZooKeeper zookeeper,Watcher watcher) throws KeeperException, InterruptedException, UnknownHostException {
        String parentPath = String.format("/%s",zookeeperProperties.getParentName());
        log.info("fooball-server parentPath:{}",parentPath);
        if(zookeeper.exists(parentPath,watcher)==null){
            zookeeper.create(parentPath,null,ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
            log.info("create parentPath {} success.",parentPath);
        }

    }

    public void createInstancePath(ZooKeeper zooKeeper,Watcher watcher) throws KeeperException, InterruptedException, UnknownHostException {
        String instancePath = String.format("/%s/%s",zookeeperProperties.getParentName(),zookeeperProperties.getInstanceName());
        zooKeeper.create(instancePath,instanceInfoToByte(),ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        log.info("create path {} success.",zookeeperProperties.getInstanceName());
    }


    public String getHost() throws UnknownHostException {
        InetAddress address = InetAddress.getLocalHost();
        return address.getHostAddress();
    }

    public InstanceInfo createInstanceInfo() throws UnknownHostException {
        String host = String.format("%s:%s",getHost(),zookeeperProperties.getServerPort());
        log.info("current instance host {}",host);
        return new InstanceInfo(zookeeperProperties.getInstanceName(),host);
    }

    public byte[] instanceInfoToByte() throws UnknownHostException {
        Gson gson=new Gson();
        InstanceInfo instanceInfo = createInstanceInfo();
        return gson.toJson(instanceInfo).getBytes();
    }



}


fooball-meta實現服務發現功能

建立Zookeeper.properties和建立讀取.properties檔案的類和football-server一致。

從Zookeeper獲取註冊服務的引數

@Service
public class MetaService implements IMetaService {

    @Autowired
    ZooKeeper zooKeeper;

    @Autowired
    ZookeeperProperties zookeeperProperties;

    @Autowired
    Watcher watcher;

    private static Logger log = LoggerFactory.getLogger(MetaService.class);

    @Override
    public List<InstanceInfo> getServiceInfo() {
        try {
            String parentPath = String.format("/%s",zookeeperProperties.getParentName());
            List<String> childs = zooKeeper.getChildren(parentPath,false);
            return getInstancesByName(childs);
        } catch (KeeperException e) {
            log.error("Zookeeper getChildren error!");
            e.printStackTrace();
        } catch (InterruptedException e) {
            log.error("Zookeeper getChildren error!");
            e.printStackTrace();
        }
        return Collections.emptyList();
    }

    public List<InstanceInfo> getInstancesByName(List<String> childs) throws KeeperException, InterruptedException {
        List<InstanceInfo> instanceInfos =new ArrayList<InstanceInfo>();
        for(String childName:childs){
            String childPath = String.format("/%s/%s",zookeeperProperties.getParentName(),childName);
            instanceInfos.add(getInstanceFromZK(childPath));
        }
        return instanceInfos;
    }

    public InstanceInfo getInstanceFromZK(String path) throws KeeperException, InterruptedException {

        byte[] data = zooKeeper.getData(path,watcher,null);
        String instanceJson = new String(data);
        return new Gson().fromJson(instanceJson,InstanceInfo.class);
    }

}