前言:环境、项目与读法

卷三所需环境与版本:Java 17(Flink 1.20 支持基线)、Kafka 3.8.1、kafka-streams-test-utils、Flink 1.20.x Java API、MiniCluster 测试配置。包含校验机器的实测版本,以及贯穿项目 eventd v3 的数据流架构(清洗→聚合→面板)与三种阅读路径。

环境准备

必须版本

组件版本说明
JDK17Flink 1.20 支持 Java 11/17;本书统一用 17
Maven3.9.12标准构建
Kafka Streams3.8.1流处理 DSL
Flink1.20.xJava DataStream API
Redis7.x面板实时缓存
Docker29.x(可选)本地启动 Kafka/Redis

不要用 JDK 25 运行 Flink 1.20:该版本的支持矩阵只有 Java 11 和 17。

校验环境(实测)

下面的版本来自实际命令输出,不是目标配置:

macOS 26.3 (25D125), Apple Silicon
默认 JDK: Zulu 8.92.0.21 (1.8.0_482)
备用 JDK: Homebrew OpenJDK 27.0.1.0.3
Maven: 3.9.12(Maven 自身运行在默认 JDK 8 上)
Docker: 29.7.2

mvn -v 显示的 Java version 取决于 JAVA_HOME。构建本书工程前先安装并切换到 JDK 17:

export JAVA_HOME=$(/usr/libexec/java_home -v 17)
java -version   # 应为 17.x
mvn -v          # Java version: 17.x

说明:作者机器未安装 JDK 17,书中的代码片段只用 JDK 27 的 javac 做过部分语法核对,未做 Flink 运行时验收;验收类数字必须由读者在目标环境生成(见 12.3)。

Maven BOM

eventd-v3/pom.xml 的依赖管理:

<properties>
    <maven.compiler.release>17</maven.compiler.release>
    <kafka.version>3.8.1</kafka.version>
    <flink.version>1.20.0</flink.version>
</properties>

<dependencies>
    <!-- Kafka Streams -->
    <dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka-streams</artifactId>
        <version>${kafka.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka-streams-test-utils</artifactId>
        <version>${kafka.version}</version>
        <scope>test</scope>
    </dependency>

    <!-- Flink -->
    <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-streaming-java</artifactId>
        <version>${flink.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-clients</artifactId>
        <version>${flink.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-connector-kafka</artifactId>
        <version>3.3.0-1.20</version>
    </dependency>
    <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-cep</artifactId>
        <version>${flink.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-statebackend-rocksdb</artifactId>
        <version>${flink.version}</version>
    </dependency>
    <!-- 测试用 MiniCluster -->
    <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-test-utils</artifactId>
        <version>${flink.version}</version>
        <scope>test</scope>
    </dependency>

    <!-- Redis -->
    <dependency>
        <groupId>io.lettuce</groupId>
        <artifactId>lettuce-core</artifactId>
        <version>6.5.1.RELEASE</version>
    </dependency>
</dependencies>

注意 Flink Connector 版本:3.3.0-1.20 表示 connector 3.3.0 适配 Flink 1.20。

贯穿项目:eventd v3

eventd v3 接收 eventd v2 产生的事件流,实时清洗、聚合、展示。

数据流

eventd v2 (WebFlux + R2DBC)
    └── 业务事件 → Kafka Producer → Topic "eventd-raw"
                                            ↓
    Kafka Streams (清洗管道)
        ├── 去重(基于事件 ID)
        ├── 格式标准化(统一字段名、类型转换)
        ├── 异常过滤(丢弃非法数据)
        └── 写入 Topic "eventd-cleaned"
                                ↓
    Flink DataStream (实时计算)
        ├── 滚动窗口:每分钟订单量
        ├── 滑动窗口:近 5 分钟平均延迟
        ├── CEP:连续 3 次失败告警
        └── 结果写入 Redis
                    ↓
    实时面板 (SSE/WebSocket)
        └── 浏览器实时刷新

模块划分

eventd-v3/
├── eventd-cleansing          # Kafka Streams 清洗管道
│   └── 拓扑定义、自定义 Processor、状态存储配置
├── eventd-analytics          # Flink DataStream 实时计算
│   ├── 窗口聚合作业
│   ├── CEP 规则引擎
│   └── 自定义 Source/Sink
├── eventd-panel              # 实时面板(WebFlux SSE)
│   └── 读取 Redis、推送到客户端
└── eventd-shared             # 共享事件模型、序列化器

测试环境

Kafka Streams:TopologyTestDriver

不需要运行 Kafka broker:

Properties props = new Properties();
props.put(StreamsConfig.APPLICATION_ID_CONFIG, "test-app");
props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "dummy:9092");

Topology topology = buildTopology();
TopologyTestDriver driver = new TopologyTestDriver(topology, props);

// 发送测试数据
TestInputTopic<String, String> input = driver.createInputTopic(
    "eventd-raw", new StringSerializer(), new StringSerializer());
input.pipeInput("key1", "{\"eventId\":\"1\",\"type\":\"order\"}");

// 读取输出
TestOutputTopic<String, String> output = driver.createOutputTopic(
    "eventd-cleaned", new StringDeserializer(), new StringDeserializer());
assertEquals("ORDER", parseType(output.readValue()));  // 清洗管道会把 type 转大写

Flink:本地执行与 MiniCluster

在 IDE 里直接运行 StreamExecutionEnvironment.getExecutionEnvironment() 就会用本地线程执行,不需要集群,也不需要手工启动 MiniCluster。

需要模拟多个 TaskManager/Slot、验证作业提交或 Checkpoint 行为时,用 JUnit 5 的 MiniClusterExtension,并通过它提供的客户端提交作业。只调用 cluster.start() 再执行 getExecutionEnvironment() 并不会把作业提交到那个集群——两者之间没有自动连接。完整写法见 13.2 Flink DataStream 测试 。

三种读法

路径 A:顺序通读(推荐)

  1. 第 1–3 章:流处理基础(Dataflow、窗口、Kafka Streams 入门)
  2. 第 4–8 章:Flink 核心(DataStream、Watermark、状态、Checkpoint、CEP)
  3. 第 9–12 章:eventd v3 实现(清洗→聚合→面板)
  4. 第 13–14 章:测试、性能、运维

路径 B:已有 Kafka Streams 经验

跳过第 2–3 章,从第 4 章(Flink DataStream)开始。重点看:

  • 第 6 章(CEP):复杂事件模式匹配
  • 第 8 章(测试与调优):MiniCluster、反压
  • 第 11 章(端到端 EOS):Kafka → Flink → 下游

路径 C:只看代码

前言(环境)→ 第 9 章(eventd v3 架构)→ 附录 A(Flink 速查)→ 附录 B(Kafka Streams 速查)。

与卷一/卷二的衔接

卷衔接点
卷一Flux/Mono 的背压概念 → Flink 的 backpressure 机制;Processor → Kafka Streams Processor API
卷二eventd v2 的事件格式 → eventd v3 的输入;WebFlux SSE → 面板推送层;Micrometer 指标 → Flink MetricsReporter

一个前置提醒

流处理代码的「正确」比「快」更难验证。批处理可以重跑,流处理的历史事件已经流逝。

本卷的示例按可测试方式组织;关键拓扑应配确定性测试:给定相同的输入事件序列,输出必须完全一致。这是流处理系统可追溯、可调试的基础。

环境就绪后,从流处理范式开始:1.1 Dataflow、窗口与时间语义 。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「java」更多文章

  1. 15.3 全书总结与学习路径回顾
  2. 15.2 响应式流处理的演进趋势
  3. 15.1 引擎选型指南