Zookeeper典型应用场景 高可用的服务注册与消费(四)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_34125999/article/details/100052929

1、项目结构

在这里插入图片描述
pom文件:

 <!--spring boot 版本依赖-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.101tec/zkclient-->
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.10</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper-->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.8</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
        </dependency>
    </dependencies>

2、生产者

在这里插入图片描述

生产者把当前ip和端口注册到zk上

2.1、pom文件

   <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

2.2、application.yml

server:
  port: 9000
zookeeper:
  ip: 192.168.92.39
  timeout: 10000

2.3、ZookeeperProviderConfig

@Configuration
public class ZookeeperProviderConfig implements InitializingBean {

    /***
     *功能描述  本地服务端口
     */
    @Value("${server.port}")
    private Integer port;

    /***
     *功能描述 zk ip
     */
    @Value("${zookeeper.ip}")
    private String zkAddress;

    /***
     *功能描述 超时时间
     */
    @Value("${zookeeper.timeout}")
    private Integer zkTimeout;

    /***
     *功能描述  zk注册的服务节点
     */
    private static final String BASE_SERVICE = "/services";
    private static final String PRODUCER_SERVICE = "/producer";

    @Override
    public void afterPropertiesSet() throws Exception {
        //1、获取本地地址
        String hostAddress = InetAddress.getLocalHost().getHostAddress();
        //2、创建Zookeeper
        ZkClient zkClient = new ZkClient(zkAddress, zkTimeout);
        //3、判断父亲节点是否存在,如果不存在创建
        if (!zkClient.exists(BASE_SERVICE)) {
            zkClient.createPersistent(BASE_SERVICE);
        }
        //4、把当前服务注册到zk中
        System.out.println(serverUrl);
        zkClient.createEphemeralSequential(BASE_SERVICE + PRODUCER_SERVICE, serverUrl);

    }
}

2.4、controller

@RestController
@RequestMapping("/zk")
public class ProviderController {

    /***
     *功能描述  本地服务端口
     */
    @Value("${server.port}")
    private Integer port;

    @GetMapping("/hello")
    public String hello() {

        return "provider " + port + " say hello";
    }

}

2.5、启动生产者,并且在idea复制一份,把端口改成9001启动
在这里插入图片描述
1)访问9000,9001端口
在这里插入图片描述
在这里插入图片描述
2)打开zk:
在这里插入图片描述

3、消费者

在这里插入图片描述

消费者用于监听生产者提供服务的根节点,如果根节点发生了变化,及时更新服务列表

3.1、pom

  <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

3.2、yml

server:
  port: 8000
zookeeper:
  ip: 192.168.92.39
  timeout: 10000

3.3、LoadBalance

public abstract class LoadBalance {

    /***
    *功能描述  服务列表
     */
    public volatile static List<String> SERVICE_LIST;
     
    /***
    *功能描述 获取一个服务
    */
    public abstract String choseServiceHost();
}

3.4.、轮询

@Configuration
public class LunXunBalance extends LoadBalance {

    private static Integer index = 0;

    /***
     *功能描述  如果服务列表不为空,就从服务列表获取一个url返回
     */
    @Override
    public String choseServiceHost() {
        if (!CollectionUtils.isEmpty(SERVICE_LIST)) {
            index++;
            if (index >= SERVICE_LIST.size()) {
                index = 0;
            }
            return SERVICE_LIST.get(index);
        }
        return null;
    }
}

3.5、ZookeeperCustomerConfig

@Configuration
public class ZookeeperCustomerConfig {

    /***
     *功能描述 zk地址
     */
    @Value("${zookeeper.ip}")
    private String zkAddress;

    /***
     *功能描述 超时时间
     */
    @Value("${zookeeper.timeout}")
    private Integer zkTimeout;

    /***
     *功能描述  zk注册的服务节点
     */
    private static final String BASE_SERVICE = "/services";


    @Bean
    public ZkClient zkClient() {
        ZkClient zkClient = new ZkClient(zkAddress, zkTimeout);
        updateServerList(zkClient);
        zkClient.subscribeChildChanges(BASE_SERVICE, new ServerWatcher(zkClient));
        return zkClient;
    }


    /**
     * 功能描述 更新服务列表
     */
    private void updateServerList(ZkClient zkClient) {
        List<String> serverList = new ArrayList<>();
        try {
            //获取节点
            List<String> childrens = zkClient.getChildren(BASE_SERVICE);
            //获取节点的值
            for (String child : childrens) {
                Object host = zkClient.readData(BASE_SERVICE + "/" + child);
                serverList.add((String) host);
            }
            //把值赋给LoadBalance
            LoadBalance.SERVICE_LIST = serverList;
            System.out.println("服务列表已经更新:" + serverList);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 功能描述  监听子节点的变换
     *
     * @author Zrs
     * @date 2019/8/24
     * @return: ......
     */
    private class ServerWatcher implements IZkChildListener {

        private ZkClient zkClient;

        public ServerWatcher(ZkClient zkClient) {
            this.zkClient = zkClient;
        }

        @Override
        public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
            updateServerList(zkClient);
        }
    }


}

.3.6、RestConfig

@Configuration
public class RestConfig {

    @Bean
    public RestTemplate restTemplate() {

        return new RestTemplate();
    }
}

3.7、 CustomerController

@RestController
@RequestMapping("/customer")
public class CustomerController {

    @Resource
    private RestTemplate restTemplate;

    @Autowired
    private LoadBalance loadBalance;

    @RequestMapping("/hello")
    public String customer() {
        String url = loadBalance.choseServiceHost();
        String hello = restTemplate.getForObject("http://" + url + "/zk/hello/", String.class);
        return hello;
    }
}

3.8、启动消费者者
在这里插入图片描述

1)第一次访问controller

在这里插入图片描述

2)第二次访问controller
在这里插入图片描述
3)停掉9001端口的客户端
在这里插入图片描述
在这里插入图片描述
4)再次访问url
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_34125999/article/details/100052929
今日推荐