深入理解Zookeeper(三)如何通过zookeeper实现服务注册中心

如何通过zookeeper实现服务注册中心

(1)发现的问题

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

(2)解决的方法

在这里插入图片描述
在这里插入图片描述

(3)代码实现

(1)UserService代码
package com.yyds.quartzstudy.service;
import org.apache.zookeeper.*;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class UserService {

    private final static String userServicePrefix = "/services/user";
    private final static String orderServicePrefix = "/services/order";

    public void userService(String ip){
        /**
         * 1、连接上zk集群
         */
        try {
            String zkAddr = "192.168.42.101:2181,192.168.42.102:2181,192.168.42.103:2181";
            // 只要执行一次countDown(),等待的线程就会继续执行
            CountDownLatch countDownLatch = new CountDownLatch(1);
            ZooKeeper zooKeeper = new ZooKeeper(zkAddr, 5000, new Watcher() {
                @Override
                public void process(WatchedEvent watchedEvent) {// 异步创建
                    countDownLatch.countDown();
                }
            });
            countDownLatch.await();
            System.out.println("userService机器-" + ip +  "  连接zk成功...");
            /**
             *  2、注册到服务注册中心
             */
            register(zooKeeper, ip);

        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * 将服务注册到服务注册中心
     */
    private void register(ZooKeeper zooKeeper, String ip) {
        String userServicePath = userServicePrefix + "/" + ip;

        /**
         * 尝试创建/services/user/{ip}节点
         *   如果创建成功,表示正常注册到服务注册中心
         *      此时需要去监听订单服务,一旦订单服务列表发生变化(新增,宕机),这里就会感知到
         *   如果创建失败,直接退出,去查ip被占用的原因
         */
        zooKeeper.create(
                userServicePath,
                ("" + ip).getBytes(),
                ZooDefs.Ids.OPEN_ACL_UNSAFE,
                CreateMode.EPHEMERAL,
                new AsyncCallback.StringCallback() {
                        @Override
                        public void processResult(int i, String s, Object o, String s1) {
                            if(i == KeeperException.Code.OK.intValue()){
                                System.out.println("userService机器-" + ip + " 将服务注册到服务注册中心成功," + "节点名称为:" + userServicePath);
                                // 需要去监听订单服务,一旦订单服务列表发生变化(新增,宕机),这里就会感知到
                                try {
                                    List<String> orderServiceList = autoFindOrderService(zooKeeper, ip);
                                    if(orderServiceList.size() < 1){
                                        System.out.println("userService机器-" + ip + " 第一次 没有发现可用的订单服务...");
                                    }else {
                                        orderServiceList.stream()
                                                .map(orderIp -> "userService机器-" + ip + " 第一次 发现可用的订单服务,orderService机器ip为:" + orderIp + "...")
                                                .forEach(System.out::println);
                                    }
                                } catch (Exception e) {
                                    e.printStackTrace();
                                    System.out.println("userService机器-" + ip + " 第一次获取order服务异常...");
                                }
                            }else if(i == KeeperException.Code.NODEEXISTS.intValue()){
                                System.out.println("userService机器-" + ip + " 将服务注册到服务注册中心失败," + "节点名称为:" + userServicePath);
                            }else {
                                System.out.println("userService机器-" + ip + " 错误," + "节点名称为:" + userServicePath);
                            }
                        }

                    /**
                     * 自动监听订单服务的列表
                     */
                    private List<String> autoFindOrderService(ZooKeeper zooKeeper, String ip) throws Exception {
                        // 需要去监听订单服务,一旦订单服务列表发生变化(新增,宕机),这里就会感知到
                        List<String> children = zooKeeper.getChildren(orderServicePrefix, new Watcher() {
                            @Override
                            public void process(WatchedEvent event) {
                                // 如果子节点发生了变化,需要获取最新的子节点列表  并且需要继续监听
                                if (event.getType() == Event.EventType.NodeChildrenChanged) {
                                    try {
                                        List<String> orderServiceList = autoFindOrderService(zooKeeper, ip);
                                        if(orderServiceList.size() < 1){
                                            System.out.println("userService机器-" + ip + " 没有发现可用的订单服务...");
                                        }else {
                                            orderServiceList.stream()
                                                    .map(orderIp -> "userService机器-" + ip + " 发现可用的订单服务,orderService机器ip为:" + orderIp + "...")
                                                    .forEach(System.out::println);
                                        }
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                        System.out.println("userService机器-" + ip + " 获取order服务异常...");
                                    }
                                }else {
                                    // 其他事件暂时不关注
                                    System.out.println("其他事件:" + event.getType().getIntValue());
                                }
                            }
                        });
                        return children;
                    }
                } ,
                "call_back");
    }
}
(2)测试代码
package com.yyds.quartzstudy.service;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;

public class ServiceTest {

    public static void main(String[] args) throws InterruptedException {
        Arrays.asList("192.168.100.10","192.168.100.11")
                .stream()
                .map(ip -> (Runnable)() -> new UserService().userService(ip))
                .map(Thread::new)
                .forEach(Thread::start);


        TimeUnit.SECONDS.sleep(10000);
    }
}
(3)order服务用zk客户端模拟
userService机器-192.168.100.11  连接zk成功...
userService机器-192.168.100.10  连接zk成功...
userService机器-192.168.100.11 将服务注册到服务注册中心成功,节点名称为:/services/user/192.168.100.11
userService机器-192.168.100.10 将服务注册到服务注册中心成功,节点名称为:/services/user/192.168.100.10
userService机器-192.168.100.10 第一次 没有发现可用的订单服务...
userService机器-192.168.100.11 第一次 没有发现可用的订单服务...
    
用zk的命令行客户端模拟订单服务上线:
[zk: localhost:2181(CONNECTED) 8] create -e /services/order/192.168.100.10 ""
Created /services/order/192.168.100.10
[zk: localhost:2181(CONNECTED) 9] create -e /services/order/192.168.100.11 ""
Created /services/order/192.168.100.11
结果如下:
userService机器-192.168.100.11 发现可用的订单服务,orderService机器ip为:192.168.100.10...
userService机器-192.168.100.10 发现可用的订单服务,orderService机器ip为:192.168.100.10...

userService机器-192.168.100.10 发现可用的订单服务,orderService机器ip为:192.168.100.10...
userService机器-192.168.100.10 发现可用的订单服务,orderService机器ip为:192.168.100.11...
userService机器-192.168.100.11 发现可用的订单服务,orderService机器ip为:192.168.100.10...
userService机器-192.168.100.11 发现可用的订单服务,orderService机器ip为:192.168.100.11...

用zk的命令行客户端模拟订单服务下线:
 [zk: localhost:2181(CONNECTED) 10] delete /services/order/192.168.100.10
 结果如下:
userService机器-192.168.100.10 发现可用的订单服务,orderService机器ip为:192.168.100.11...
userService机器-192.168.100.11 发现可用的订单服务,orderService机器ip为:192.168.100.11...
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值