zookeeper的基本概念

zookeeper底层通信是用netty实现的

 

安装zookeeper,并配置集群

1、准备三台机器做集群

服务器

IP地址

端口

服务器1

192.168.10.140

2181/2881/3881

服务器2

192.168.10.141

2181/2881/3881

服务器3

192.168.10.142

2181/2881/3881

2、配置

2.1配置java环境

将jdk-8u141-linux-x64.tar.gz上传到三台服务器安装配置。

解压到/data/program/software/

并将文件夹重命名为java8

配置jdk全局变量。

#vi /etc/profile

export JAVA_HOME=/data/program/software/java8

export JRE_HOME=/data/program/software/java8/jre

export CLASSPATH=.:$CLASSPATH:$JAVA_HOME/lib:$JRE_HOME/lib

export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin

2.2 修改操作系统的/etc/hosts文件,添加IP与主机名映射:

   # zookeeper cluster servers

192.168.10.140 bigdata1

192.168.10.141 bigdata2

192.168.10.142 bigdata3

2.3下载zookeeper-3.4.9.tar.gz 到/data/program/software/目录

# wget http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.9/zookeeper-3.4.9.tar.gz

2.4 解压zookeeper安装包,并对节点重民名

#tar -zxvf zookeeper-3.4.9.tar.gz

服务器1:

#mv zookeeper-3.4.9 zookeeper

服务器2:

    #mv zookeeper-3.4.9 zookeeper

服务器3:

#mv zookeeper-3.4.9 zookeeper

2.5 在zookeeper的各个节点下 创建数据和日志目录

#cd zookeeper

#mkdir data

#mkdir logs

2.6 重命名配置文件

    将zookeeper/conf目录下的zoo_sample.cfg文件拷贝一份,命名为zoo.cfg:

#cp zoo_sample.cfg zoo.cfg

修改zoo.cfg 配置文件

clientPort=2181

dataDir=/data/program/software/zookeeper/data

dataLogDir=/data/program/software/zookeeper/logs

server.1=bigdata1:2881:3881

server.2=bigdata2:2881:3881

server.3=bigdata3:2881:3881

参数说明:

tickTime=2000

tickTime这个时间是作为Zookeeper服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个tickTime时间就会发送一个心跳。

initLimit=10

initLimit这个配置项是用来配置Zookeeper接受客户端(这里所说的客户端不是用户连接Zookeeper服务器的客户端,而是Zookeeper服务器集群中连接到Leader的Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过10个心跳的时间(也就是tickTime)长度后Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是10*2000=20 秒。

syncLimit=5

syncLimit这个配置项标识Leader与Follower之间发送消息,请求和应答时间长度,最长不能超过多少个tickTime的时间长度,总的时间长度就是5*2000=10秒。

dataDir=/data/program/software/zookeeper/data

dataDir顾名思义就是Zookeeper保存数据的目录,默认情况下Zookeeper将写数据的日志文件也保存在这个目录里。

clientPort=2181

clientPort这个端口就是客户端(应用程序)连接Zookeeper服务器的端口,Zookeeper会监听这个端口接受客户端的访问请求。

server.A=B:C:D

server.1=bigdata1:2881:3881

server.2=bigdata2:2881:3881

server.3=bigdata3:2881:3881

A是一个数字,表示这个是第几号服务器;

B是这个服务器的IP地址(或者是与IP地址做了映射的主机名);

C第一个端口用来集群成员的信息交换,表示这个服务器与集群中的Leader服务器交换信息的端口;

D是在leader挂掉时专门用来进行选举leader所用的端口。

注意:如果是伪集群的配置方式,不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。

2.8 创建myid文件

在dataDir= dataDir=/data/program/software/zookeeper/data 下创建myid文件

编辑myid文件,并在对应的IP的机器上输入对应的编号。如在1上,myid文件内容就是1, 2上就是2, 3上就是3:

#vi /myid## 值为1

#vi /myid## 值为2

#vi /myid## 值为3

2.9 启动测试zookeeper

(1)进入/bin目录下执行:

# /zkServer.sh start

# /zkServer.sh start

# /zkServer.sh start

(2)输入jps命令查看进程:

其中,QuorumPeerMain是zookeeper进程,说明启动正常

(3)查看状态:

   # /zkServer.sh status

 (4)查看zookeeper服务输出信息:

 由于服务信息输出文件在/bin/zookeeper.out

$ tail -500 f zookeeper.out

连接客户端:

./zkClient.sh -server 192.168.10.140:2181, 192.168.10.141:2181, 192.168.10.142:2181,

 

3、集群角色

Leader:写操作都走leader,zk里面leader只有一个

Fllower: 帮leader处理查的请求,有投票的权利

Observer:进行指定,没有投票权利,可以处理请求

ZK的常用命令

Ls:查看那目录的所有文件

Ls2:多了一些参数,time,version等

Create:创建节点,并设置初始内容,创建的时候必须以/开始,其实是存储数据的,该数据叫znode。可以创建父子节点:create /lpf/node lpf666,数据为lpf666.

Get:获取znode的数据

Set :修改znode的数据

Delete:删除znode

Quit:退出客户端

Help:

Rmr:进行递归删除,可以删除子节点

4、Zk的核心概念:

Zk其实是做存储的。

Znode:用来存储数据的。zk操作和维护的是一个一个的数据节点,采用类似于文件系统的层级树状结构进行管理。如果znode节点包含数据则存储为字节数组,创建znode需要制定类型:

·持久:客户端创建的文件一直存在,退出后文件还会存在。默认为此。PERISTENT

·持久有序节点PERSISTENT_SEQUENTIAL:是有序的,创建出来的文件是带有序号的:Create -s  /lpf lpf666

·ephemeral临时的:客户端session失效,则数据消失。

Create -e  /lpf lpf666  退出后该节点没了

·Ephemeral_sequential临时有序节点:有序自增

Dubbo连接zk,用的是临时节点,因为dubbo,服务正常后才保存session,如果服务停了,zk中的数据消失,通过查看节点判断服务是否正常

 

5、Watcher机制:

时间监听器

当某个节点数据变化的时候,所有的客户端都会感知,从而被通知。可以实现多级缓存数据一致性问题

 

6、ACL:

Zk的权限管理

getAcl /lpf   返回word

word:谁都可以访问

auth:代表已经认证通过的用户

digest:即用户名,密码方式认证,常用的方式

addauth digest lpf:lpf

create /aaa 123456

setAcl /aaa auth:lpf:lpf:cdrwa权限

用其他客户端get /aaa的时候就不行了

ip:ip地址认证

 

7、高性能:

Zk不适合海量数据的存储,高性能体现在读多写少的场景。因为fllower很多,leader只有一个。

 

客户端操作:

  1. zk原生操作
  2. zkClient操作

ZkClient是由Datameer的工程师开发的开源客户端,对Zookeeper的原生API进行了包装,实现了超时重连、Watcher反复注册等功能。

github源代码地址:https://github.com/sgroschupf/zkclient

 

  1. curator

流式接口

 

Zk的使用场景:

  1. 分布式配置中心
  2. 分布式锁

利用watcher监听节点,对并发不高的可以使用

  1. 服务注册与订阅

Dubbo

Zk的原理

入口程序:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.apache.zookeeper.server.quorum;

import java.io.File;
import java.io.IOException;
import javax.management.JMException;
import org.apache.zookeeper.jmx.ManagedUtil;
import org.apache.zookeeper.server.DatadirCleanupManager;
import org.apache.zookeeper.server.ServerCnxnFactory;
import org.apache.zookeeper.server.ZKDatabase;
import org.apache.zookeeper.server.ZooKeeperServerMain;
import org.apache.zookeeper.server.persistence.FileTxnSnapLog;
import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class QuorumPeerMain {
    private static final Logger LOG = LoggerFactory.getLogger(QuorumPeerMain.class);
    private static final String USAGE = "Usage: QuorumPeerMain configfile";
    protected QuorumPeer quorumPeer;

    public QuorumPeerMain() {
    }

    public static void main(String[] args) {
        QuorumPeerMain main = new QuorumPeerMain();

        try {
            main.initializeAndRun(args);
        } catch (IllegalArgumentException var3) {
            LOG.error("Invalid arguments, exiting abnormally", var3);
            LOG.info("Usage: QuorumPeerMain configfile");
            System.err.println("Usage: QuorumPeerMain configfile");
            System.exit(2);
        } catch (ConfigException var4) {
            LOG.error("Invalid config, exiting abnormally", var4);
            System.err.println("Invalid config, exiting abnormally");
            System.exit(2);
        } catch (Exception var5) {
            LOG.error("Unexpected exception, exiting abnormally", var5);
            System.exit(1);
        }

        LOG.info("Exiting normally");
        System.exit(0);
    }

    protected void initializeAndRun(String[] args) throws ConfigException, IOException {
        QuorumPeerConfig config = new QuorumPeerConfig();
        if(args.length == 1) {
            config.parse(args[0]);
        }

        DatadirCleanupManager purgeMgr = new DatadirCleanupManager(config.getDataDir(), config.getDataLogDir(), config.getSnapRetainCount(), config.getPurgeInterval());
        purgeMgr.start();
        if(args.length == 1 && config.servers.size() > 0) {
            this.runFromConfig(config);
        } else {
            LOG.warn("Either no config or no quorum defined in config, running  in standalone mode");
            ZooKeeperServerMain.main(args);
        }

    }

    public void runFromConfig(QuorumPeerConfig config) throws IOException {
        try {
            ManagedUtil.registerLog4jMBeans();
        } catch (JMException var4) {
            LOG.warn("Unable to register log4j JMX control", var4);
        }

        LOG.info("Starting quorum peer");

        try {
            ServerCnxnFactory cnxnFactory = ServerCnxnFactory.createFactory();
            cnxnFactory.configure(config.getClientPortAddress(), config.getMaxClientCnxns());
            this.quorumPeer = new QuorumPeer();
            this.quorumPeer.setClientPortAddress(config.getClientPortAddress());
            this.quorumPeer.setTxnFactory(new FileTxnSnapLog(new File(config.getDataLogDir()), new File(config.getDataDir())));
            this.quorumPeer.setQuorumPeers(config.getServers());
            this.quorumPeer.setElectionType(config.getElectionAlg());
            this.quorumPeer.setMyid(config.getServerId());
            this.quorumPeer.setTickTime(config.getTickTime());
            this.quorumPeer.setMinSessionTimeout(config.getMinSessionTimeout());
            this.quorumPeer.setMaxSessionTimeout(config.getMaxSessionTimeout());
            this.quorumPeer.setInitLimit(config.getInitLimit());
            this.quorumPeer.setSyncLimit(config.getSyncLimit());
            this.quorumPeer.setQuorumVerifier(config.getQuorumVerifier());
            this.quorumPeer.setCnxnFactory(cnxnFactory);
            this.quorumPeer.setZKDatabase(new ZKDatabase(this.quorumPeer.getTxnFactory()));
            this.quorumPeer.setLearnerType(config.getPeerType());
            this.quorumPeer.setSyncEnabled(config.getSyncEnabled());
            this.quorumPeer.setQuorumListenOnAllIPs(config.getQuorumListenOnAllIPs().booleanValue());
            this.quorumPeer.start();
            this.quorumPeer.join();
        } catch (InterruptedException var3) {
            LOG.warn("Quorum Peer interrupted", var3);
        }

    }
}

 

 

org.apache.zookeeper.server.quorum.QuorumPeerMain.main

  >org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun

   >org.apache.zookeeper.server.quorum.QuorumPeerConfig.parse //解析zoo.cfg文件内容加载到内存中

    >org.apache.zookeeper.server.quorum.QuorumPeerMain.runFromConfig  启动准备工作

     >org.apache.zookeeper.server.quorum.QuorumPeer 创建QuorumPeer对象

      >org.apache.zookeeper.server.quorum.QuorumPeer.start 1、加载数据库 2、网络建立启动 3、leader选举

1加载数据库

2、网络建立启动

org.apache.zookeeper.server.ServerCnxnFactory.start   nio和netty两个factnroy

org.apache.zookeeper.server.NIOServerCnxnFactory.start

3、leader选举

> org.apache.zookeeper.server.ZooKeeperServerMain.main

单机模式:/org/apache/zookeeper/server/quorum/QuorumPeerMain.java:116

 

你可能感兴趣的:(中间件)