功能点 1:项目骨架与启动流程 —— 源码阅读笔记

功能点 1:项目骨架与启动流程 ------ 源码阅读笔记

对应源码阅读计划功能点 1:理解 Fluss 的模块组织、CoordinatorServer 和 TabletServer 的完整启动流程、Standby/Leader 状态机、ZooKeeper 注册机制。


笔记 1.1:CoordinatorServer 完整启动链路

文件:CoordinatorServer.java

路径fluss-server/src/main/java/org/apache/fluss/server/coordinator/CoordinatorServer.java


1. 入口与主流程

java 复制代码
public static void main(String[] args) {
    Configuration configuration =
        loadConfiguration(args, CoordinatorServer.class.getSimpleName());
    applyServerDefaultConfigurations(configuration);
    CoordinatorServer coordinatorServer = new CoordinatorServer(configuration);
    startServer(coordinatorServer);
}

调用链

复制代码
main()
  → loadConfiguration(args)       ← 从 args/fluss-conf.yaml 加载配置
  → applyServerDefaultConfigurations()
  → new CoordinatorServer(conf)   ← 构造函数:生成 serverId(UUID) + 验证配置
  → startServer(server)           ← 继承自 ServerBase,触发 startServices()
      → startServices()
          → electCoordinatorLeaderAsync()  ★ 核心启动逻辑

2. 两阶段启动:Standby → Leader

这是 CoordinatorServer 最核心的设计模式------先以 Standby 身份启动基础设施,再竞选 Leader 加载协调逻辑

java 复制代码
private void electCoordinatorLeaderAsync() throws Exception {
    // 阶段 1:Standby 模式启动
    initCoordinatorStandby();

    // 阶段 2:通过 ZooKeeper 竞选 Leader
    // 成功后回调 → initCoordinatorLeader()
    // 失败后回调 → cleanupCoordinatorLeader()
    coordinatorLeaderElection.startElectLeaderAsync(
        () -> {
            try {
                initCoordinatorLeader();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        },
        (Throwable t) -> {
            try {
                cleanupCoordinatorLeader();
            } catch (Exception e) {
                LOG.error("Failed to cleanup coordinator leader services", e);
            }
        });
}

设计思想解析

复制代码
Server 启动
    │
    ├── 1. initCoordinatorStandby()
    │   ├── ZK 连接 (ephemeral node 注册)
    │   ├── RPC Server 启动(只响应健康检查)
    │   ├── MetadataManager 初始化(只读模式)
    │   ├── Scheduler / IO Executor 启动
    │   ├── MetricRegistry + 监控指标
    │   ├── Authorizer 初始化
    │   └── DynamicConfigManager 启动(监听配置变更)
    │
    └── 2. 竞选 Leader(异步)
        ├── [竞选成功] → initCoordinatorLeader()
        │   ├── ZK Fence (epoch +1)   ← 防脑裂
        │   ├── RpcClient 创建        ← Leader 需要主动连接 TabletServer
        │   ├── CoordinatorEventProcessor 启动 ← 核心事件循环
        │   ├── AutoPartitionManager 启动
        │   ├── CoordinatorChannelManager 创建
        │   └── createDefaultDatabase()  ← 创建默认数据库
        │
        └── [失去Leader] → cleanupCoordinatorLeader()
            ├── 关闭 RpcClient
            ├── 关闭 EventProcessor
            ├── 关闭 ChannelManager
            └── 恢复 DynamicConfigManager 监听
                → 回到 Standby 状态,等待下次竞选

3. 脑裂防护:ZK Fence 机制

java 复制代码
protected void initCoordinatorLeader() throws Exception {
    // ★ 关键步骤:通过 ZK epoch 防止脑裂
    ZkEpoch zkEpoch = zkClient.fenceBecomeCoordinatorLeader(serverId);
    registerCoordinatorLeader();
    // ...
    CoordinatorContext coordinatorContext = new CoordinatorContext(zkEpoch);
    // 后续所有操作都携带这个 epoch,旧 Leader 的请求会被拒绝
}

工作原理

  • ZK 上有一个递增的 epoch 值
  • 新 Leader 竞选成功时,epoch +1
  • 旧 Leader 如果还没意识到自己已不再是 Leader,其携带旧 epoch 的写操作会被 ZK 拒绝
  • CoordinatorContext 保存当前 epoch,传递给 CoordinatorEventProcessor 等组件

4. 关键设计模式

模式 实现位置 目的
GuardedBy 锁保护 synchronized(lock) + @GuardedBy("lock") 所有 20+ 个服务组件在启动/关闭时线程安全
CompletableFuture 链 terminationFuture 异步关闭流程
AtomicBoolean 防重入 isShutDown 确保 shutdown 只执行一次
重试模式 registerToZookeeperWithRetry() ZK 临时节点可能残留,需要重试注册
防御式清理 try-catch 包裹每个 cleanup 步骤 任何一个清理失败不影响其余

5. 默认数据库创建逻辑

java 复制代码
private void createDefaultDatabase() {
    List<String> databases = metadataManager.listDatabases();
    if (databases.isEmpty()) {
        metadataManager.createDatabase("fluss", DatabaseDescriptor.EMPTY, true);
    }
    if (conf.get(ConfigOptions.KAFKA_ENABLED)) {
        String kafkaDB = conf.get(ConfigOptions.KAFKA_DATABASE);
        if (!databases.contains(kafkaDB)) {
            metadataManager.createDatabase(kafkaDB, DatabaseDescriptor.EMPTY, true);
        }
    }
}

首次启动时自动创建 fluss 默认数据库。若启用了 Kafka 兼容模式,还会额外创建 Kafka 默认数据库。


笔记 1.2:TabletServer 启动流程

文件:TabletServer.java

路径fluss-server/src/main/java/org/apache/fluss/server/tablet/TabletServer.java

启动流程

TabletServer 的启动比 CoordinatorServer 简单------它不需要 Leader 选举,启动后直接向 Coordinator 注册即可:

java 复制代码
// TabletServer 启动链路(简化)
startServices()
  → 1. 初始化 ZK 连接
  → 2. 创建 RpcServer(处理客户端读写请求)
  → 3. 初始化 LogManager(管理所有 LogTablet)
  → 4. 初始化 KvManager(管理所有 KvTablet/RocksDB 实例)
  → 5. 初始化 ReplicaManager(管理 Leader/Follower 角色)
  → 6. 初始化 MetricRegistry
  → 7. 向 ZK 注册 TabletServer 节点
  → 8. 开始接收 Coordinator 下发的 Tablet 加载指令

TabletServer 与 CoordinatorServer 的交互

复制代码
TabletServer 启动
    │
    ├── 注册到 ZK (ephemeral node)
    │   路径: /fluss/tablet_servers/{server_id}
    │
    ├── CoordinatorEventProcessor 检测到新节点
    │   └── 触发 Rebalance / Tablet 分配
    │
    └── Coordinator 下发 LoadTablet RPC
        └── TabletServer.loadTablet(assignment)
            ├── 加载 LogTablet(创建/打开日志段)
            ├── 如果是 PK 表 → 加载 KvTablet(打开 RocksDB)
            └── 如果是 Follower → 启动 ReplicaFetcher

关键差异

  • CoordinatorServer:有状态机(Standby ↔ Leader),启动需要竞选
  • TabletServer:无状态机,启动即服务,被动接收 Tablet 分配

笔记 1.3:ServerBase 基类与模块组织

文件:ServerBase.java + pom.xml

模块依赖关系

pom.xml 可以推导出模块依赖层级:

复制代码
fluss-dist (发行版)
  └── fluss-server (服务端)
        ├── fluss-common (公共组件:配置、元数据、Arrow 工具)
        ├── fluss-rpc (Protobuf + Netty RPC)
        ├── fluss-client (客户端 SDK)
        ├── fluss-metrics (监控指标)
        └── fluss-filesystems (S3/HDFS 文件系统)

fluss-flink
  └── fluss-flink-common (Flink Connector 公共模块)
        ├── fluss-flink-1.20 (Flink 1.20 适配)
        ├── fluss-flink-2.2  (Flink 2.2 适配)
        └── fluss-flink-tiering (Flink 驱动的 Tiering)

fluss-spark
  └── Spark Connector

fluss-kafka
  └── Kafka 协议兼容层

ServerBase 核心职责

java 复制代码
public abstract class ServerBase {
    protected final Configuration conf;
    protected final PluginManager pluginManager;
    
    // 模板方法模式
    protected abstract void startServices() throws Exception;  // 子类实现
    protected abstract CompletableFuture<Result> closeAsync(Result result);
    
    // 通用工具
    protected static Configuration loadConfiguration(String[] args, String serverName);
    protected static void startServer(ServerBase server);
    protected static void applyServerDefaultConfigurations(Configuration conf);
}

设计分析

  • ServerBase 是所有服务端组件的抽象基类,定义了生命周期模板
  • startServices() 是抽象方法,由 CoordinatorServerTabletServer 各自实现
  • 配置加载、JVM 参数、默认值设置都在基类中统一处理

阅读小结

已理解 尚未深入
✅ CoordinatorServer 的 Standby→Leader 两阶段启动 ⬜ ZkEpoch 的具体实现
✅ 脑裂防护的 ZK Fence 机制 ⬜ ZK 临时节点注册/重试的细节
✅ 关键组件的初始化顺序和依赖关系 ⬜ PluginManager 的加载机制
✅ TabletServer 的启动流程和被动加载模式 ⬜ 具体的 RPC 协议定义(Protobuf)
✅ 模块依赖关系 CoordinatorLeaderElection 内部实现

下一步 :进入功能点 2------深入 MetadataManagerTableManager,理解表的创建、修改、删除的完整生命周期。

相关推荐
PC2005-cloud1 小时前
Elasticsearch 学习笔记:集群实战(3 控制节点 + 3 数据节点部署与故障转移)
笔记·学习·elasticsearch
Rsingstarzengjx1 小时前
stm32m157 U-boot 测试
linux·运维·服务器
墨雨晨曦882 小时前
2026/08/16 AI学习笔记
笔记·学习
workflower2 小时前
智能无人机成低空经济核心赛道
运维·人工智能·机器学习·机器人·云计算·无人机
CarIise2 小时前
C语言基础课程笔记:硬件原理、数据类型、结构体与格式化输入输出详解
c语言·开发语言·笔记
张小姐的猫3 小时前
【Linux】网络编程 —— 传输层协议 TCP(下)
linux·运维·服务器·网络·tcp/ip·http·php
程序员AlbertTu3 小时前
第2章 上手 Linux:环境与文件操作
linux·运维·服务器
今儿敲了吗3 小时前
CN——数据链路层(下)
网络·笔记
RainCityLucky3 小时前
Java Swing 自定义组件库分享(十六)
java·笔记·后端