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/zh-hant/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

發表回復

登錄後才能評論