大数据学习心得2020-09-10--Zookeeper基本学习与模拟服务器动态上下线监听API实现

ZooKeeper

Zookeeper简介

  • 概述

    zookeeper是一个开源的分布式的,为分布式应用提供协调服务地Aoache项目。

    zookeeper是基于观察者模式的分布式服务管理框架。

    ​ 它负责存储和管理大家都关心的数据,然后接受观察者的注册。一旦这些数据发生变化,zk就负责通知所有已经在zk上注册的那些观察者做出的响应的反应。

    zookeeper = 文件系统 + 通知系统

  • 特点

    • zk是由一个leader和多个follower组成的集群
    • 集群中只要有半数以上的节点存活,zk集群就能正常服务
    • 全局数据一致,每个server保存一份相同的数据副本,client不论连接那个额server,得到的数据都是一样的
    • 更新请求一致:来自同一个client的更新请求按其发送的顺序依次执行
    • 数据更新原子性
    • 实时性:在一定时间范围内,client能读取到最新的数据
  • 数据结构

    zookeeper的数据模型与Unix文件系统很类似,整体上可以看作一棵树,每个节点称作一个znode。每个znode默认能够存储1m的数据,每个znode都可以i通过其路径唯一标识。
    大数据学习心得2020-09-10--Zookeeper基本学习与模拟服务器动态上下线监听API实现_第1张图片

  • 应用场景

    提供诸如统一命名、统一配置、统一集群管理、服务器动态上下线、软负载均衡

    • 统一命名服务:在分布式环境下对应用、服务等统一命名、便于识别。

      例如:ip不好记忆而域名容易记住

    • 统一配置管理:一般一个集群中的配置文件要求所有节点一致,如Kafka的集群。这个配置管理就可以由zookeeper实现

    • 统一集群管理:在分布式中,实时掌握每个节点状态是必要的,zk可以实现实时监控节点状态变化

    • 服务器动态上下线:客户端能实时洞察到服务器的上下线的变化

    • 软负载均衡:zk中记录了Metairie服务器的访问数,让访问数最少的服务器处理最新的客户端请求

      • 注意:软负载均衡指通过软件代码实现负载均衡,对应的,硬负载均衡对应着通过对硬件的调整是西安负载均衡
  • 下载官网:https://zookeeper.apache.org/

zookeeper的安装

​ 考虑到zk的安装基本是机械操作且网上教材甚多,此处略过不表

  • 在配置文件zoo.cfg的时候有配置到

    ​ server.A=B:C:D

    • 其中A是一个数字,表示这个是第几号服务器
    • B是这个服务器的地址
    • C是这个服务器Follower与集群中的Leader服务器交换信息的端口
    • D是万一集群中的Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,而这个端口就是用来执行选举时服务器相互通信的端口
  • 集群启动

    zk需要单点分别启动:

    bin/zkServer.sh start

    类似的通过如下指令查看状态

    bin/zkServer.sh status

zookeeper实战练习

客户端命令行操作

命令基本语法 功能描述
help 显示所有操作命令
ls path [watch] 使用 ls 命令来查看当前znode中所包含的内容
ls2 path [watch] 查看当前节点数据并能看到更新次数等数据
create 普通创建
-s 含有序列
-e 临时(重启或者超时消失)
get path [watch] 获得节点的值
set 设置节点的具体值
stat 查看节点状态
delete 删除节点
rmr 递归删除节点 *rm -r

API应用

  • 环境的搭建

    • pom文件依赖:

      <dependencies>
      		<dependency>
      			<groupId>junitgroupId>
      			<artifactId>junitartifactId>
      			<version>RELEASEversion>
      		dependency>
      		<dependency>
      			<groupId>org.apache.logging.log4jgroupId>
      			<artifactId>log4j-coreartifactId>
      			<version>2.8.2version>
      		dependency>
      		
      		<dependency>
      			<groupId>org.apache.zookeepergroupId>
      			<artifactId>zookeeperartifactId>
      			<version>3.4.10version>
      		dependency>
      dependencies>
      
    • 在ersouces目录下创建log4j.properties文件,文件中写入:

      log4j.rootLogger=INFO, stdout  
      log4j.appender.stdout=org.apache.log4j.ConsoleAppender  
      log4j.appender.stdout.layout=org.apache.log4j.PatternLayout  
      log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n  
      log4j.appender.logfile=org.apache.log4j.FileAppender  
      log4j.appender.logfile.File=target/spring.log  
      log4j.appender.logfile.layout=org.apache.log4j.PatternLayout  
      log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
      
  • 通过API对znode的增删改查功能

  • 模拟监听服务器节点的动态上下线

    • 服务器

      public class DistributedServer {
          //zookeeper的服务器访问路径
          private String path = "hadoop201:2181,hadoop202:2181,hadoop203:2181";
          //连接超时时间
          private int sessionTimeout = 2000;
          //由zookeeper提供的连接类
          private ZooKeeper zkCli;
          //这里将/servers作为znode的父节点,
          //所有服务器上线都在父节点下注册一个临时有序的子节点
          private String parentNode = "/servers";
      
          /***
           * 获取连接
           */
          public void getConnect() throws Exception{
              zkCli = new ZooKeeper(path, sessionTimeout, new Watcher() {
                  public void process(WatchedEvent watchedEvent) {}
              });
          }
      
          /***
           * 服务器注册方法,为对应的服务器在父节点中注册一个znode
           * @param info 此条为创建节点是用到的数据,一般为服务器的hostname
           */
          public void register(String info)
                  throws KeeperException, InterruptedException {
              String serverNode = zkCli.create(
              						parentNode + "/server", info.getBytes(), 
              							ZooDefs.Ids.OPEN_ACL_UNSAFE, 
              			 					CreateMode.EPHEMERAL_SEQUENTIAL);
              System.out.println(info+" is online: "+serverNode);
          }
      
          /***
           * 模拟服务器的业务方法
           * 负责将服务器进程进行死循环阻塞,防止服务器进程关闭
           */
          public void business() throws Exception{
              System.out.println("server start working ...");
              while(true){
                  Thread.sleep(5000);
                  System.out.println("keep alive ...");
              }
          }
      
          /***
           * 通过建立服务器进程摸拟服务器的上下线
           * @param args
           * @throws Exception
           */
          public static void main(String[] args) throws Exception{
              //创建一个服务器对象
              DistributedServer ds = new DistributedServer();
              //获取zk连接
              ds.getConnect();
              //注册服务器
              ds.register("hs101:login");
              //服务器开始业务流程(阻塞模拟)
              ds.business();
          }
      }
      
    • 客户端

      public class Client {
          //四个属性同服务器属性
          private String path = "hadoop201:2181,hadoop202:2181,hadoop203:2181";
          private int sessionTimeout = 2000;
          private ZooKeeper zkCli;
          private String parentNode = "/servers";
      
          /***
           * 同服务器,获取连接
           */
          public void getConnect() throws Exception{
              zkCli = new ZooKeeper(path, sessionTimeout, new Watcher() {
                  public void process(WatchedEvent watchedEvent) {}
              });
          }
      
          /***
           * 检测父节点“/servers”是否存在,如果不存在,则创建之
           */
          public void checkExist() throws Exception{
              Stat exists = zkCli.exists("/servers", false);
              if (exists == null){
                  zkCli.create("/servers","servers".getBytes(),
                          ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
              }
          }
      
          /***
           * 获取服务器端数据,创建监听器
           */
          public void getServers() throws Exception{
              //捕获父节点下子节点的变动情况,并将返回值存入list中
              List<String> children = zkCli.getChildren(
                      "/servers", new Watcher() {
                  public void process(WatchedEvent watchedEvent) {
                      System.out.println("servers changed.");
                      try {
                          //递归调用本方法在创建一个监听器保持对zk中
                          //“/servers”端口下znode变化的持续监听
                          getServers();
                      } catch (Exception e) {
                          e.printStackTrace();
                      }
                  }
              });
              //新建list用于分析children对应的znode中存储的数据
              List<String> result = new ArrayList<String>();
              for (String child : children) {
                  //通过zkclient的gerData方法获取每一个子节点的数据
                  byte[] info = zkCli.getData(
                  					parentNode + "/" + child, false, null);
                  result.add(new String(info));
              }
              //输出
              System.out.println("最新的信息是:"+result);
          }
          
          //模拟业务造成线程阻塞,防止线程关闭
          public void business() throws Exception{
              while (true){
                  Thread.sleep(5000);
                  System.out.println("keep alive ...");
              }
          }
          public static void main(String[] args) throws Exception{
              //新建客户端对象
              Client client = new Client();
              //与zk取得连接
              client.getConnect();
              //检查/servers父节点是否存在
              client.checkExist();
              //建立监听器,获取每一次/servers下每一次znode的变化情况
              client.getServers();
              //客户端业务
              client.business();
          }
      }
      

你可能感兴趣的:(大数据学习笔记,zookeeper,java,分布式,大数据)