k8szookeeper详解

一、zookeeper简介

Apache ZooKeeper是一个开源的分布式协调服务,可以为分布式应用程序提供高效且可靠的分布式协调服务。它是Hadoop和Kafka等著名分布式系统的重要组成部分。ZooKeeper可以看作是分布式应用程序基础设施的核心,提供了诸如数据同步、配置管理、分布式锁、分布式队列等功能。ZooKeeper采用了集中式的设计和分布式的实现,是一种典型的Paxos算法实现,通过数据的“write-once, read-many”方式提供高性能、高可靠性的服务,具有良好的可扩展性和可靠性。

二、k8szookeeper基础操作

创建zookeeper服务

我们可以通过kubernetes创建zookeeper服务,我们可以通过以下yml示例来创建一个zookeeper服务:

apiVersion: v1
kind: Service
metadata:
  name: my-zookeeper-service
spec:
  selector:
    app: my-zookeeper
  ports:
    - name: zk-client
      protocol: TCP
      port: 2181
      targetPort: 2181
    - name: zk-server
      protocol: TCP
      port: 2888
      targetPort: 2888
    - name: zk-election
      protocol: TCP
      port: 3888
      targetPort: 3888
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: my-zookeeper
spec:
  serviceName: my-zookeeper-service
  replicas: 3
  selector:
    matchLabels:
      app: my-zookeeper
  template:
    metadata:
      labels:
        app: my-zookeeper
    spec:
      containers:
      - name: zookeeper
        image: zookeeper:3.4.9
        ports:
        - containerPort: 2181
        - containerPort: 2888
        - containerPort: 3888
        volumeMounts:
        - name: data
          mountPath: /data
        - name: conf
          mountPath: /conf
        command: ["/bin/bash"]
        args: ["-c", "ln -s /conf/zoo.cfg ./conf/zoo.cfg; zkServer.sh start-foreground"]
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: my-zk-pvc
      - name: conf
        configMap:
          name: my-zk-cm

访问zookeeper服务

我们可以通过Port Forwarding的方式在本地直接访问zookeeper服务,具体操作步骤如下所示:

1. 获取zookeeper服务的pod名称:

$ kubectl get pods

2. 执行Port Forwarding命令:

$ kubectl port-forward  2181:2181

3. 在本地通过2181端口访问zookeeper服务:

$ zkCli -server localhost:2181

配置zookeeper

我们可以通过配置文件来修改zookeeper的配置信息,例如我们可以修改zookeeper的dataDir、clientPort等参数。以下为zookeeper的配置文件示例:

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data
clientPort=2181
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

监控zookeeper

ZooKeeper提供了丰富的监控指标,可以通过JMX监控、ZooKeeper-Monitor、Cadvisor等工具对其进行监控。下面我们将介绍如何通过JMX监控zookeeper。

监控zookeeper的JMX指标

我们可以通过添加如下JAVA_OPTS来启用JMX监控ZooKeeper:

-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.port=7199
-Djava.rmi.server.hostname=192.168.XX.XX

然后我们可以通过JConsole等JMX监控工具来访问ZooKeeper的JMX端口,获取ZooKeeper的监控指标信息。

三、k8szookeeper集群管理

创建k8szookeeper集群

我们可以通过kubernetes创建k8szookeeper集群,以下为创建一个3节点k8szookeeper集群的yml示例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: zookeeper-config
data:
  zoo.cfg: |
    tickTime=2000
    initLimit=10
    syncLimit=5
    dataDir=/data
    clientPort=2181
    server.1=zoo1:2888:3888
    server.2=zoo2:2888:3888
    server.3=zoo3:2888:3888
---
apiVersion: v1
kind: Service
metadata:
  name: zookeeper
spec:
  ports:
  - name: zk-client
    port: 2181
    targetPort: 2181
  clusterIP: None
  selector:
    app: zookeeper
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: zookeeper
spec:
  replicas: 3
  serviceName: zookeeper
  selector:
    matchLabels:
      app: zookeeper
  template:
    metadata:
      labels:
        app: zookeeper
    spec:
      containers:
      - name: zookeeper
        image: zookeeper:3.4.9
        ports:
        - containerPort: 2181
          name: client
        - containerPort: 2888
          name: server
        - containerPort: 3888
          name: election
        env:
        - name: ZOO_MY_ID
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: ZOO_SERVERS
          value: "server.1=zookeeper-0.zookeeper:2888:3888 server.2=zookeeper-1.zookeeper:2888:3888 server.3=zookeeper-2.zookeeper:2888:3888"
        volumeMounts:
        - name: datadir
          mountPath: /data
        - name: config-volume
          mountPath: /conf
      volumes:
      - name: datadir
        persistentVolumeClaim:
          claimName: zookeeper-pv-claim
      - name: config-volume
        configMap:
          name: zookeeper-config

增加k8szookeeper节点

我们可以通过以下步骤来增加k8szookeeper节点:

1. 创建一个新的zookeeper服务,并指定新的serverID。

2. 修改zookeeper集群中已有节点的配置文件,添加新的server。

3. 将新的zk数据目录复制到新的服务器中。

4. 启动新的节点,并加入到zookeeper集群中。

删除k8szookeeper节点

我们可以通过以下步骤来删除k8szookeeper节点:

1. 停止zk服务。

2. 从zookeeper集群配置文件中删除该节点的配置信息。

3. 删除该节点的数据目录。

四、k8szookeeper应用场景

分布式锁

ZooKeeper提供一个基于节点的锁系统,可以用于分布式系统中的锁定需求。分布式锁是一个常见的需求,例如分布式计算、分布式任务调度、分布式事务等等。ZooKeeper作为一个分布式协调服务,可以提供高效、稳定、可靠的分布式锁服务。下面是一个Java实现的分布式锁示例:

public class DistributedLock {
    
    private static final String LOCK_ROOT = "/locks";
    
    private ZooKeeper zk;
    private String lockName;
    
    private String lockPath;
    private String watchNode;
    private String currentNode;
    
    public DistributedLock(ZooKeeper zk, String lockName) {
        this.zk = zk;
        this.lockName = lockName;
    }
    
    public void lock() throws Exception {
        // 创建锁的根目录
        Stat stat = zk.exists(LOCK_ROOT, false);
        if (stat == null) {
            zk.create(LOCK_ROOT, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }
        
        // 创建锁节点
        lockPath = zk.create(LOCK_ROOT + "/" + lockName, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        currentNode = lockPath.substring(lockPath.lastIndexOf("/") + 1);
        
        // 获取所有的子节点,并排序
        List children = zk.getChildren(LOCK_ROOT, false);
        Collections.sort(children);
        
        if (currentNode.equals(children.get(0))) {
            // 获取锁
            return;
        } else {
            // 同步监控当前节点的前一个节点
            int index = Collections.binarySearch(children, currentNode);
            watchNode = children.get(index - 1);
            zk.getData(LOCK_ROOT + "/" + watchNode, true, null);
        }
        
        // 等待前一个节点释放锁
        synchronized (this) {
            wait();
        }
    }
    
    public void unlock() throws Exception {
        zk.delete(lockPath, -1);
    }
    
    public void process(WatchedEvent event) {
        if (event.getType() == Event.EventType.NodeDeleted && event.getPath().equals(LOCK_ROOT + "/" + watchNode)) {
            synchronized (this) {
                notifyAll();
            }
        }
        try {
            zk.getData(LOCK_ROOT + "/" + watchNode, true, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

分布式配置管理

ZooKeeper可以用作分布式配置管理工具,从而实现了分布式系统中的配置管理。通过在ZooKeeper中创建一个节点作为配置存储的根目录,然后以配置文件的形式保存系统配置信息,即可用ZooKeeper实现分布式配置管理。下面是一个Java实现的分布式配置管理示例:

public class ConfigManager {
    
    private ZooKeeper zk;
    private Watcher watcher;
    
    private Config config;
    
    private static final String CONFIG_NODE = "/config";
    
    public ConfigManager(ZooKeeper zk, Config config) {
        this.zk = zk;
        this.config = config;
        this.watcher = new Watcher() {
            public void process(WatchedEvent event) {
                if (event.getType() == Event.EventType.NodeDataChanged) {
                    try {
                        byte[] data = zk.getData(CONFIG_NODE, watcher, null);
                        String configStr = new String(data, "UTF-8");
                        ConfigManager.this.config.load(configStr);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                 }
             }
         };
    }
    
    public void syncConfig() throws Exception {
        Stat stat = zk.exists(CONFIG_NODE, watcher);
        if (stat == null) {
            zk.create(CONFIG_NODE, "".getBytes("UTF-8"), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        } else {
            byte[] data = zk.getData(CONFIG_NODE, watcher, null);
            String configStr = new String(data, "UTF-8");
            this.config.load(configStr);
        }
    }
    
    public Config getConfig() {
        return config;
    }
    
    public void submitConfig(String configStr) throws Exception {
        Stat stat = zk.exists(CONFIG_NODE, false);
        if (stat == null) {
            zk.create(CONFIG_NODE, "".getBytes("UTF-8"), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }
        zk.setData(CONFIG_NODE, configStr.getBytes("UTF-8"), -1);
    }
}

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/297975.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝的头像小蓝
上一篇 2024-12-28 12:17
下一篇 2024-12-28 12:17

相关推荐

  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25
  • 神经网络代码详解

    神经网络作为一种人工智能技术,被广泛应用于语音识别、图像识别、自然语言处理等领域。而神经网络的模型编写,离不开代码。本文将从多个方面详细阐述神经网络模型编写的代码技术。 一、神经网…

    编程 2025-04-25
  • Python输入输出详解

    一、文件读写 Python中文件的读写操作是必不可少的基本技能之一。读写文件分别使用open()函数中的’r’和’w’参数,读取文件…

    编程 2025-04-25
  • git config user.name的详解

    一、为什么要使用git config user.name? git是一个非常流行的分布式版本控制系统,很多程序员都会用到它。在使用git commit提交代码时,需要记录commi…

    编程 2025-04-25
  • 详解eclipse设置

    一、安装与基础设置 1、下载eclipse并进行安装。 2、打开eclipse,选择对应的工作空间路径。 File -> Switch Workspace -> [选择…

    编程 2025-04-25
  • Java BigDecimal 精度详解

    一、基础概念 Java BigDecimal 是一个用于高精度计算的类。普通的 double 或 float 类型只能精确表示有限的数字,而对于需要高精度计算的场景,BigDeci…

    编程 2025-04-25
  • MPU6050工作原理详解

    一、什么是MPU6050 MPU6050是一种六轴惯性传感器,能够同时测量加速度和角速度。它由三个传感器组成:一个三轴加速度计和一个三轴陀螺仪。这个组合提供了非常精细的姿态解算,其…

    编程 2025-04-25
  • C语言贪吃蛇详解

    一、数据结构和算法 C语言贪吃蛇主要运用了以下数据结构和算法: 1. 链表 typedef struct body { int x; int y; struct body *nex…

    编程 2025-04-25
  • nginx与apache应用开发详解

    一、概述 nginx和apache都是常见的web服务器。nginx是一个高性能的反向代理web服务器,将负载均衡和缓存集成在了一起,可以动静分离。apache是一个可扩展的web…

    编程 2025-04-25
  • Python安装OS库详解

    一、OS简介 OS库是Python标准库的一部分,它提供了跨平台的操作系统功能,使得Python可以进行文件操作、进程管理、环境变量读取等系统级操作。 OS库中包含了大量的文件和目…

    编程 2025-04-25

发表回复

登录后才能评论