Skip to content

Zookeeper 详解:服务注册与分布式协调

  Spring Cloud Zookeeper 是 Apache ZooKeeper 的 Spring 集成,提供服务注册发现配置管理功能。ZooKeeper 本身是一个分布式协调服务,在 Spring Cloud 生态中可作为 Eureka 的替代方案使用。

一、ZooKeeper 是什么?

  ZooKeeper 是 Apache 顶级的分布式协调服务,最初为 Hadoop 生态设计,现已成为分布式系统的核心基础设施。它基于 ZAB 协议(ZooKeeper Atomic Broadcast)保证数据一致性。

┌──────────────────────────────────────────────────────────────────┐
│                    ZooKeeper 核心能力                              │
│                                                                  │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐            │
│  │  服务注册     │  │  配置管理     │  │  分布式锁     │            │
│  ├──────────────┤  ├──────────────┤  ├──────────────┤            │
│  │ 临时节点注册  │  │ 持久节点存储  │  │ 临时顺序节点  │            │
│  │ Watcher 监控 │  │ Watcher 推送 │  │ 羊群效应处理  │            │
│  └──────────────┘  └──────────────┘  └──────────────┘            │
│                                                                  │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐            │
│  │  集群选主     │  │  分布式队列   │  │  命名服务     │            │
│  ├──────────────┤  ├──────────────┤  ├──────────────┤            │
│  │ Leader 选举   │  │ 顺序节点     │  │ 全局唯一 ID   │            │
│  │ 主备切换     │  │ 分布式屏障   │  │ 命名空间     │            │
│  └──────────────┘  └──────────────┘  └──────────────┘            │
└──────────────────────────────────────────────────────────────────┘

二、核心架构

┌──────────────────────────────────────────────────────────────────┐
│                      ZooKeeper 集群                               │
│                                                                  │
│  ┌────────────┐  ┌────────────┐  ┌────────────┐                  │
│  │  Server 1  │  │  Server 2  │  │  Server 3  │                  │
│  │  (Leader)  │◄─┤ (Follower) │◄─┤ (Follower) │  ← ZAB 协议      │
│  └─────┬──────┘  └─────┬──────┘  └─────┬──────┘                  │
│        │               │               │                          │
│        └───────────────┼───────────────┘                          │
│                        │                                          │
│                        ▼                                          │
│              ┌──────────────────┐                                 │
│              │   客户端连接       │                                 │
│              └────────┬─────────┘                                 │
│                       │                                           │
│       ┌───────────────┼───────────────┐                           │
│       │               │               │                           │
│       ▼               ▼               ▼                           │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐                        │
│  │ order-   │  │ user-    │  │ inventory│                        │
│  │ service  │  │ service  │  │ -service │                        │
│  └──────────┘  └──────────┘  └──────────┘                        │
└──────────────────────────────────────────────────────────────────┘

数据模型(树形结构):

/services                          ← 持久节点
  ├── /order-service               ← 持久节点
  │   ├── /instance-001            ← 临时节点(服务关闭自动删除)
  │   │   └── data: {host: "192.168.1.10", port: 8080}
  │   └── /instance-002            ← 临时节点
  │       └── data: {host: "192.168.1.11", port: 8080}
  ├── /user-service
  │   └── /instance-001
  └── /inventory-service
      └── /instance-001

/config                            ← 配置管理
  ├── /application
  │   └── data: {common: "value"}
  └── /order-service
      └── data: {datasource: "..."}

三、快速上手

3.1 启动 ZooKeeper

bash
# Docker 启动
docker run -d -p 2181:2181 zookeeper:3.8

3.2 依赖

xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zookeeper-config</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

3.3 服务注册配置

yaml
spring:
  application:
    name: order-service
  cloud:
    zookeeper:
      connect-string: localhost:2181
      discovery:
        enabled: true
        root: /services                    # 服务注册根路径
        register: true                     # 启动时注册
        instance-id: ${spring.application.name}:${random.value}
        prefer-ip-address: true
        metadata:
          version: "1.0"
          env: dev

3.4 配置管理

yaml
spring:
  cloud:
    zookeeper:
      config:
        enabled: true
        root: /config                      # 配置根路径
        default-context: application       # 默认上下文
        watcher:
          enabled: true                    # 监听配置变更

配置创建方式:

bash
# ZooKeeper CLI 创建配置
zkCli.sh

create /config ""
create /config/application ""
create /config/application/order.limit "200"
create /config/order-service ""
create /config/order-service/datasource.url "jdbc:mysql://localhost:3306/orders"
java
@RestController
@RefreshScope
public class OrderController {

    @Value("${order.limit:100}")
    private int limit;

    @GetMapping("/limit")
    public String getLimit() {
        return "当前限流阈值:" + limit;
    }
}

四、核心机制:临时节点与 Watcher

4.1 临时节点(Ephemeral Node)

服务注册的核心机制:

1. order-service 启动 → 创建临时节点 /services/order-service/instance-001
2. order-service 存活 → 定期发送心跳(Session)
3. order-service 宕机 → Session 超时 → 临时节点被 ZK 自动删除
4. 其他服务通过 Watcher 感知到节点删除 → 从可用列表移除该实例

优势: 不需要像 Eureka 那样依赖心跳续约,ZK 的 Session 机制天然保证故障感知。

4.2 Watcher 机制

配置变更通知流程:

1. 应用启动时注册 Watcher 到 /config/order-service
2. 管理员修改 /config/order-service 的数据
3. ZK 触发 Watcher 事件,通知应用
4. 应用重新加载配置,@RefreshScope Bean 重建
5. 新配置生效

Watcher 是一次性的,触发后需要重新注册。Spring Cloud Zookeeper 自动处理了重新注册。

五、ZooKeeper vs Consul vs Nacos

维度ZooKeeperConsulNacos
CAP 模型CP(强一致性)CP(强一致性)AP + CP(可切换)
配置中心需 Spring Cloud Zookeeper Config需 Spring Cloud Consul Config内置
健康检查基于 Session(无主动检查)HTTP/TCP/gRPC/ScriptHTTP/TCP/MySQL
控制台无(需第三方工具)✅(Web UI)✅(Web UI)
一致性协议ZABRaftRaft + Distro
数据模型树形节点KV 存储服务+配置分离
学习成本
适用场景已有 ZK 基础设施非阿里云,多数据中心阿里云生态

选型建议:

已有 ZK 基础设施(如 Kafka、Dubbo) → ZooKeeper(复用,减少运维成本)
新项目,无特殊要求                    → Nacos 或 Consul
需要 Web 控制台                      → 不选 ZooKeeper
需要强大的健康检查                    → 不选 ZooKeeper(基于 Session 而非主动探测)

六、常见问题

6.1 Session 超时导致服务误下线

yaml
# 调整 Session 超时时间
spring:
  cloud:
    zookeeper:
      session-timeout: 30s     # 默认 60s,GC 频繁时可适当加大
      connection-timeout: 15s

6.2 大量 Watcher 的羊群效应

当某个配置节点被大量服务监听时,一个变更会触发所有服务同时响应,造成瞬时压力。Spring Cloud Zookeeper 通过随机延迟触发来缓解。

6.3 临时节点残留

ZooKeeper 3.6+ 支持 TTL 节点,可设置过期时间自动清理。旧版本可通过 curator 定期清理。

七、面试要点

Q1:ZooKeeper 的临时节点和持久节点有什么区别?

  临时节点与客户端 Session 绑定,客户端断开连接后自动删除,用于服务注册(服务下线后自动清除)。持久节点永久存在,需手动删除,用于存储配置数据。

Q2:ZooKeeper 如何实现服务发现?

  服务提供者启动时创建临时节点(如 /services/order-service/instance-001),服务消费者通过 Watcher 监听节点变化,当服务上下线时自动更新可用实例列表。

Q3:ZooKeeper 的 Watcher 机制是什么?

  Watcher 是 ZK 的发布订阅机制。客户端对某个节点注册 Watcher,当节点数据变化或子节点变化时,ZK 主动通知客户端。Watcher 是一次性的,触发后需重新注册。

Q4:ZooKeeper 和 Nacos 怎么选?

  已有 ZK 基础设施(如 Kafka、Dubbo)选 ZK 以复用运维体系;新项目选 Nacos(功能更完善、有 Web 控制台、支持主动健康检查)。ZK 在 Spring Cloud 中不如 Nacos 和 Consul 常用。