GKLBB

当你经历了暴风雨,你也就成为了暴风雨

导航

软件开发 --- Zookeeper 之初体验

 

使用 Zookeeper 实现一个简单的服务注册与发现功能

Zookeeper 简介

Zookeeper 是一个分布式协调服务,主要用于分布式系统中的数据共享、状态同步和服务发现等。常见的应用场景包括:分布式锁、配置管理、服务注册与发现等。

1. 安装 Zookeeper

首先,我们需要在本地或服务器上安装 Zookeeper,安装步骤如下:

1.1 下载并解压 Zookeeper

  • 访问 Zookeeper 官方网站,下载最新版本的 Zookeeper。
  • 解压下载的文件,例如将其解压到 /usr/local/zookeeper(Linux)或 C:\zookeeper(Windows)目录。

1.2 配置 Zookeeper

Zookeeper 需要配置一个配置文件 zoo.cfg。在解压目录下,conf 文件夹中有一个模板配置文件 zoo_sample.cfg,你可以复制一份并重命名为 zoo.cfg

cp conf/zoo_sample.cfg conf/zoo.cfg

1.3 配置文件内容(zoo.cfg

打开 zoo.cfg 文件并确保以下内容存在(基本配置):

# 设置 Zookeeper 数据存储路径
dataDir=/tmp/zookeeper
# 设置 Zookeeper 服务运行的端口
clientPort=2181
# 启用 Zookeeper 服务器集群模式(如果是单机模式,可以不需要修改)
# server.1=localhost:2888:3888
  • dataDir 是 Zookeeper 存储数据的目录。
  • clientPort 是客户端连接 Zookeeper 服务的端口,默认是 2181

1.4 启动 Zookeeper

在命令行中运行以下命令启动 Zookeeper:

bin/zkServer.sh start  # Linux/macOS

Windows 用户运行 zkServer.cmd 文件。

你可以运行以下命令来检查 Zookeeper 的状态:

bin/zkServer.sh status  # Linux/macOS

2. Java 环境配置

Zookeeper 是一个 Java 应用程序,操作 Zookeeper 需要通过 Java 客户端。

2.1 添加 Zookeeper 依赖

在你的 Maven 项目中,添加以下依赖:

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

2.2 创建服务注册与发现的 Zookeeper 使用案例

下面,我们实现一个服务注册与发现的案例。假设我们有多个服务,它们会将自己注册到 Zookeeper,其他服务通过查询 Zookeeper 获取服务的地址和端口。

3. Zookeeper 服务注册与发现

我们将演示如何在 Zookeeper 中实现服务的注册和发现。服务注册时,服务会在 Zookeeper 上创建临时节点,而客户端则通过监视这些节点来发现服务。

3.1 服务注册端(Server)

服务注册端负责将服务信息(比如服务名、IP 地址、端口等)注册到 Zookeeper 上。

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;

public class ServiceRegister {
    private static final String ZK_ADDRESS = "localhost:2181";
    private static final String SERVICE_PATH = "/services/my-service";
    private static ZooKeeper zk;
    private static CountDownLatch latch = new CountDownLatch(1);

    public static void main(String[] args) throws Exception {
        // 创建 Zookeeper 客户端
        zk = new ZooKeeper(ZK_ADDRESS, 3000, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                if (event.getState() == Event.KeeperState.SyncConnected) {
                    latch.countDown();
                }
            }
        });

        latch.await(); // 等待连接建立

        // 注册服务
        String serviceInfo = "127.0.0.1:8080";
        String nodePath = SERVICE_PATH + "/node_1"; // 服务节点路径

        // 如果该节点不存在,创建临时节点
        Stat stat = zk.exists(SERVICE_PATH, false);
        if (stat == null) {
            // 如果服务路径不存在,创建服务路径
            zk.create(SERVICE_PATH, "Service Registry".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }

        // 创建临时节点,表示服务实例
        String createdNode = zk.create(nodePath, serviceInfo.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);

        System.out.println("Service registered at path: " + createdNode);
        zk.close();
    }
}

代码说明:

  • Zookeeper 客户端:我们通过 ZooKeeper 类创建客户端,连接到 Zookeeper 服务。
  • 服务注册:我们在 Zookeeper 中注册服务时,会在 /services/my-service 路径下创建一个临时节点,节点的数据是服务的地址(例如 127.0.0.1:8080)。
  • 临时节点:创建的节点是临时节点(CreateMode.EPHEMERAL),意味着当 Zookeeper 断开与客户端的连接时,该节点会自动删除。

3.2 服务发现端(Client)

服务发现端通过监听 Zookeeper 上的服务节点来发现可用的服务。

import org.apache.zookeeper.*;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class ServiceDiscovery {
    private static final String ZK_ADDRESS = "localhost:2181";
    private static final String SERVICE_PATH = "/services/my-service";
    private static ZooKeeper zk;
    private static CountDownLatch latch = new CountDownLatch(1);

    public static void main(String[] args) throws Exception {
        // 创建 Zookeeper 客户端
        zk = new ZooKeeper(ZK_ADDRESS, 3000, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                if (event.getState() == Event.KeeperState.SyncConnected) {
                    latch.countDown();
                }
            }
        });

        latch.await(); // 等待连接建立

        // 监听服务节点的变化
        List<String> services = zk.getChildren(SERVICE_PATH, true); // true 表示监听节点变化

        System.out.println("Services available: ");
        for (String service : services) {
            byte[] data = zk.getData(SERVICE_PATH + "/" + service, false, null);
            System.out.println("Service: " + service + ", Data: " + new String(data));
        }

        // 关闭 Zookeeper 客户端
        zk.close();
    }
}

代码说明:

  • Zookeeper 客户端:客户端与 Zookeeper 进行连接。
  • 监听服务节点getChildren 方法用来获取服务路径下的所有子节点(即注册的服务实例),并设置监听器,实时更新服务状态。
  • 获取服务信息:通过 getData 方法获取服务节点的数据(即服务地址)。

4. 运行流程

  1. 启动 Zookeeper:首先启动 Zookeeper 服务,确保它在本地运行。
  2. 注册服务:运行 ServiceRegister 类,模拟服务注册过程。它会将服务信息(如 127.0.0.1:8080)注册到 Zookeeper。
  3. 发现服务:运行 ServiceDiscovery 类,模拟服务发现过程。它会监听 Zookeeper 上的 /services/my-service 路径,获取所有注册的服务信息。

5. 总结

在这个例子中,我们展示了如何使用 Zookeeper 来实现服务注册与发现。具体步骤包括:

  • 在 Zookeeper 中注册服务,使用临时节点存储服务信息。
  • 通过 Zookeeper 的监视机制,动态获取并更新服务列表。

Zookeeper 就像是一个“指挥中心”,它在分布式系统中解决了很多协调和同步的问题。这里是它常见的用途:

  1. 分布式锁:它能确保多个服务不会同时去做会发生冲突的事情,类似于排队等候,只让一个人执行任务。

  2. 配置管理:就像是一个配置仓库,所有服务从这里获取配置信息,保证每个服务用的是同样的配置。

  3. 服务注册与发现:它让各个服务之间互相知道对方的“位置”,比如“我在这里,大家可以来找我”。

  4. 领导者选举:当需要决定谁来做某个任务时,Zookeeper 负责选举一个“领导”,其他人都得跟着。

  5. 分布式队列:它帮助多个服务按顺序处理任务,确保任务一个接一个,不会乱跑。

  6. 通知机制:它能实时通知其他服务,某个数据或配置发生了变化,大家得更新一下。

posted on 2024-12-10 06:00  GKLBB  阅读(4)  评论(0编辑  收藏  举报