Zookeeper

2022-02-24  本文已影响0人  请叫我平爷

简介

集群机器id

myid,它是每一个集群机器中的编号文件,代表 ZooKeeper 集群服务器的标识,手动生成,全局全一

事务 ID

zxid,Zookeeper 会给每个更新请求分配一个事务 ID,它是一个 64 位的数字,由 Leader 统一进行分配,全局唯一,不断递增,在一个节点的状态信息中可以查看到最新的事务 ID 信息。

集群服务器角色

服务器状态

选举方式

选举场景

选举条件

选举流程

启动顺序为zk1,zk2,zk3

  1. 初始化选举
    初始投票:每个server都会给自己投一票,myid和zxid,zk(myid,zxid)比如zk1(1,0),zk(2,0),zk(3,0)
    同步投票结果:各自的投票结果同步给集群其他服务器
    检查投票的有效性:本轮的投票的server是否处于LOOKING状态
    处理投票:先检查zxid,较大的服务器优先,zxid相同,myid较大的服务器作为Leader,zk1启动,zk2启动与zk1比较,zk1改成(2,0)
    统计投票结果:是否有超过半数的机器的投票结果一样,(2,0)有两票,zk2当选
    更改服务器状态:选好了Leader,每个服务器更新自己的状态,zk1->FOLLOWING,zk2->LEADING,zk3->FOLLOWING
  2. 集群重新选举
    状态变更:Leader不能用了,所有的Follower从FOLLOWING改成LOOKING,开始新一轮选举
    开始投票:
    同步投票结果
    检查投票的有效性
    处理投票
    统计投票结果
    更改服务器状态

特征

安装

cd /usr/local
wget https://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.6.2/apache-zookeeper-3.6.2-bin.tar.gz
# 解压zookeeper
tar -zxvf apache-zookeeper-3.6.2-bin.tar.gz
cd apache-zookeeper-3.6.2-bin
cd conf/
# 重命名配置文件zoo_sample.cfg
cp zoo_sample.cfg zoo.cfg
cd ../
# 启动zookeeper
bin/zkServer.sh start

# 停止
bin/zkServer.sh stop

# 查看状态
bin/zkServer.sh status

github地址

下载地址

集群搭建

把zookeeper文件复制为4份,zookeeper01、zookeeper02、zookeeper03、zookeeper-client

  1. 修改zookeeper01/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/Users/biostime/Documents/java/zookeeper/zookeeper01/data
dataLogDir=/Users/biostime/Documents/java/zookeeper/zookeeper01/log
clientPort=2181
server.1=10.50.101.123:2287:3387
server.2=10.50.101.123:2288:3388
server.3=10.50.101.123:2289:3389
  1. 新建zookeeper01/data/myid,内容是1
  1. 修改zookeeper02/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/Users/biostime/Documents/java/zookeeper/zookeeper02/data
dataLogDir=/Users/biostime/Documents/java/zookeeper/zookeeper02/log
clientPort=2182
server.1=10.50.101.123:2287:3387
server.2=10.50.101.123:2288:3388
server.3=10.50.101.123:2289:3389
  1. 新建zookeeper02/data/myid,内容是2

  2. 修改zookeeper03/conf/zoo.cfg

    tickTime=2000
    initLimit=10
    syncLimit=5
    dataDir=/Users/biostime/Documents/java/zookeeper/zookeeper03/data
    dataLogDir=/Users/biostime/Documents/java/zookeeper/zookeeper03/log
    clientPort=2183
    server.1=10.50.101.123:2287:3387
    server.2=10.50.101.123:2288:3388
    server.3=10.50.101.123:2289:3389
    
  3. 新建zookeeper03/data/myid,内容是3

  4. 然后启动所有的zookeeper

    cd bin/
    ./zkServer.sh start
    

    输入jps后,会出现三个QuorumPeerMain进程

  5. 进入zookeeper-client的bin目录下

    # 连接到zookeeper01上
    ./zkCli.sh -timeout 5000 -server 127.0.0.1:2181
    

zookeeper监控某个值的变化

pom.xml

                <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.13</version>
        </dependency>

java代码:

package com.example.zookeeper6001.config;

import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

public class ZookeeperProSync implements Watcher {

    private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
    private static ZooKeeper zk = null;
    private static Stat stat = new Stat();

    public static void main(String[] args) throws Exception {
        //zookeeper配置数据存放路径
        String path = "/zookeeper6001";
        //连接zookeeper并且注册一个默认的监听器
        zk = new ZooKeeper("127.0.0.1:2181", 5000, //
                new ZookeeperProSync());
        //等待zk连接成功的通知
        connectedSemaphore.await();
        //获取path目录节点的配置数据,并注册默认的监听器
        System.out.println(new String(zk.getData(path, true, stat)));

        Thread.sleep(Integer.MAX_VALUE);
    }

    public void process(WatchedEvent event) {
        if (KeeperState.SyncConnected == event.getState()) {  //zk连接成功通知事件
            if (EventType.None == event.getType() && null == event.getPath()) {
                connectedSemaphore.countDown();
            } else if (event.getType() == EventType.NodeDataChanged) {  //zk目录节点数据变化通知事件
                try {
                    System.out.println("配置已修改,新值为:" + new String(zk.getData(event.getPath(), true, stat)));
                } catch (Exception e) {
                }
            }
        }

    }
}

zookeeper命令

# 创建一个树节点
create /zookeeper6001 zookeeper6001Info

# 获取某个节点的内容
get /zookeeper6001 

# 更新某个节点的内容
set /zookeeper6001 zookeeper6001InfoChange

java代码会打印

配置已修改,新值为:zookeeper6001InfoChange

zookeeper+openfeign

provider

  1. pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>zookeeper-provider-8001</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>zookeeper-provider-8001</name>
    <description>mi</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
    </properties>


    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
        </dependency>

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

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
  1. ZookeeperProvider8001Application

    @EnableDiscoveryClient
    
  2. ProviderController

    package com.example.zookeeperprovider8001.controller;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class ProviderController {
    
        @RequestMapping("/hello")
        public String hello(){
            String res = "ProviderController hello success";
            System.out.println(res);
            return res;
        }
    
    }
    
  3. application.properties

    server.port=8001
    
    spring.application.name=service-provider
    spring.cloud.zookeeper.connect-string=127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183
    

comsumer

  1. pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>zookeeper-comsumer-8002</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>zookeeper-comsumer-8002</name>
    <description>mi</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

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

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
  1. ZookeeperComsumer8002Application

    @EnableFeignClients
    
  2. ComsumerService

    package com.example.zookeepercomsumer8002.server;
    
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    
    @FeignClient(contextId = "comsumerService", value = "service-provider")
    public interface ComsumerService {
    
        @GetMapping("/hello")
        String hello();
        
    }
    
  3. ComsumerController

package com.example.zookeepercomsumer8002.controller;

import com.example.zookeepercomsumer8002.server.ComsumerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ComsumerController {

    @Autowired
    ComsumerService service;

    @RequestMapping("/comsumer")
    public String comsumer(){
        String res = service.hello();
        System.out.println(res);
        return res;
    }


}
  1. application.properties

    server.port=8002
    
    spring.application.name=service-comsumer
    feign.client.config.default.connect-timeout=500
    feign.client.config.default.read-timeout=500
    spring.cloud.zookeeper.connect-string=127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183
    
    feign.hystrix.enabled=true
    

连接到其中一台zookeeper

# 查询所有的
ls /
# [services, zookeeper, zookeeper6001]

# 查询services
ls /services
# [service-comsumer, service-provider]

# 查询service-comsumer
ls /services/service-comsumer
# [7ee01bb1-9e58-4923-b8c8-6dfff5590f85]

# 查询[7ee01bb1-9e58-4923-b8c8-6dfff5590f85]
get /services/service-comsumer/7ee01bb1-9e58-4923-b8c8-6dfff5590f85
# {"name":"service-comsumer","id":"7ee01bb1-9e58-4923-b8c8-6dfff5590f85","address":"10.50.101.123","port":8002,"sslPort":null,"payload":{"@class":"org.springframework.cloud.zookeeper.discovery.ZookeeperInstance","id":"application-1","name":"service-comsumer","metadata":{"instance_status":"UP"}},"registrationTimeUTC":1609747347415,"serviceType":"DYNAMIC","uriSpec":{"parts":[{"value":"scheme","variable":true},{"value":"://","variable":false},{"value":"address","variable":true},{"value":":","variable":false},{"value":"port","variable":true}]}}

当停掉provider和comsumer后,过一段时间,zookeeper下的/services节点会自动删除

上一篇 下一篇

猜你喜欢

热点阅读