1.3 Flink 环境搭建

Flink Java 开发环境搭建:Maven BOM 与依赖引入、本地 MiniCluster 测试配置、StreamExecutionEnvironment 创建与参数设置,以及第一个可运行 WordCount DataStream 作业的完整代码与验证步骤。

Maven 配置

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

<dependencies>
    <!-- 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>

    <!-- Kafka 连接器 -->
    <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-connector-kafka</artifactId>
        <version>3.3.0-1.20</version>
    </dependency>

    <!-- CEP -->
    <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-cep</artifactId>
        <version>${flink.version}</version>
    </dependency>

    <!-- RocksDB 状态后端(用到 EmbeddedRocksDBStateBackend 时必须显式引入) -->
    <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-statebackend-rocksdb</artifactId>
        <version>${flink.version}</version>
    </dependency>

    <!-- 测试 -->
    <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-test-utils</artifactId>
        <version>${flink.version}</version>
        <scope>test</scope>
    </dependency>
</dependencies>

注意两点:

  • flink-connector-kafka 的版本号 3.3.0-1.20 中,3.3.0 是 connector 版本,1.20 是 Flink 版本。必须匹配你的 Flink 版本。
  • maven.compiler.release 用 17。Flink 1.20 只支持 Java 11 和 17,用 21 或 25 编译虽然能过,运行时不受支持。

经典的 WordCount,用 DataStream API:

import java.time.Duration;

import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.assigners.TumblingProcessingTimeWindows;
import org.apache.flink.util.Collector;

public class WordCount {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env =
            StreamExecutionEnvironment.getExecutionEnvironment();

        // 设置并行度(默认 = CPU 核心数)
        env.setParallelism(2);

        // Source:从 socket 读取(开发测试用)
        DataStream<String> text = env.socketTextStream("localhost", 9999);

        // Transformation:分词 + 计数
        DataStream<Tuple2<String, Integer>> wordCounts = text
            .flatMap(new Tokenizer())
            .keyBy(value -> value.f0)
            .window(TumblingProcessingTimeWindows.of(Duration.ofSeconds(5)))
            .sum(1);

        // Sink:打印到控制台
        wordCounts.print();

        // 启动作业
        env.execute("Socket WordCount");
    }

    static class Tokenizer implements FlatMapFunction<String, Tuple2<String, Integer>> {
        @Override
        public void flatMap(String value, Collector<Tuple2<String, Integer>> out) {
            for (String word : value.split(" ")) {
                out.collect(new Tuple2<>(word.toLowerCase(), 1));
            }
        }
    }
}

运行方式

方式 1:本地 MiniCluster(开发)

# 启动 netcat 发送数据
nc -lk 9999

# 另开终端运行作业
mvn compile exec:java -Dexec.mainClass="WordCount"

# 在 nc 终端输入:
hello world
hello flink
hello java

# 控制台输出:
# (hello, 3)
# (world, 1)
# (flink, 1)
# (java, 1)

getExecutionEnvironment() 在 IDE 里返回 LocalStreamEnvironment:它在同一个 JVM 里用多线程执行作业,不需要外部集群。它不是 MiniCluster——没有独立 TaskManager 进程,也不能通过它验证提交、Slot 分配或跨进程网络。需要这些能力时,用下一节的显式 MiniCluster。

方式 2:显式 MiniCluster(测试)

import org.apache.flink.runtime.testutils.MiniClusterResourceConfiguration;
import org.apache.flink.test.util.MiniClusterWithClientResource;

public class FlinkTest {
    @ClassRule
    public static MiniClusterWithClientResource cluster =
        new MiniClusterWithClientResource(
            new MiniClusterResourceConfiguration.Builder()
                .setNumberSlotsPerTaskManager(2)
                .setNumberTaskManagers(1)
                .build());
}

JUnit 4 的 @ClassRule 在测试类开始前启动 MiniCluster,测试结束后自动关闭。MiniClusterWithClientResource 在 1.20 仍可用;JUnit 5 项目改用 org.apache.flink.test.junit5.MiniClusterExtension,它会把启动、关闭和执行上下文一起管好,写法见 13.2 。

StreamExecutionEnvironment 配置

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

// 并行度
env.setParallelism(4);

// 时间语义:由每个 Source 的 WatermarkStrategy 决定,没有全局开关

// Checkpoint 配置(第 5.3 节详细展开)
env.enableCheckpointing(60000);  // 每 60 秒 Checkpoint,语义默认 EXACTLY_ONCE

// 重启策略
env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3, Duration.ofSeconds(10)));

// 状态后端
env.setStateBackend(new HashMapStateBackend());
env.getCheckpointConfig().setCheckpointStorage("file:///tmp/flink-checkpoints");

常见问题

问题原因解决
NoResourceAvailableExceptionTask slot 不足(并行度大于可用 slot 数)降低并行度,或增加 TaskManager/slot;不要靠调大并行度解决
ClassNotFoundException: KafkaSourceconnector 版本不匹配确认 flink-connector-kafka 版本与 Flink 版本匹配
输出乱序使用了 Processing Time改用 Event Time + Watermark
作业不退出execute() 阻塞主线程正确,流作业是长期运行的;测试用 env.executeAsync()
本地端口冲突MiniCluster 默认端口被占修改 RestOptions.PORT

本地运行时,Flink 启动 Web UI(默认端口 8081):

http://localhost:8081

可查看:

  • 作业 DAG(数据流拓扑图)
  • 各算子的背压状态
  • Checkpoint 历史
  • 任务日志

eventd-v3 的 analytics 模块配置:

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(4);
env.enableCheckpointing(30000);
env.getCheckpointConfig().setMinPauseBetweenCheckpoints(10000);
env.getCheckpointConfig().setCheckpointTimeout(60000);
env.getCheckpointConfig().setMaxConcurrentCheckpoints(1);
env.setRestartStrategy(RestartStrategies.fixedDelayRestart(5, Duration.ofSeconds(30)));
env.setStateBackend(new EmbeddedRocksDBStateBackend());
env.getCheckpointConfig().setCheckpointStorage("file:///var/flink/checkpoints");
参数值原因
parallelism4开发机 4 核
checkpointing interval30s平衡容错与性能
minPauseBetweenCheckpoints10s防止 Checkpoint 过于密集
maxConcurrentCheckpoints1顺序执行,减少 I/O 压力
restart attempts5短暂故障自动恢复
state backendRocksDB大状态(窗口内数据多)时内存安全

小结

概念说明
StreamExecutionEnvironment作业入口,配置全局参数
getExecutionEnvironment()自动检测环境(本地/集群)
setParallelism()全局并行度
enableCheckpointing()开启容错快照
setStateBackend()状态存储后端
MiniCluster本地测试无需外部集群
Web UIlocalhost:8081 查看作业状态

第 1 章结束。下一节 2.1 Kafka Streams 拓扑 。

继续阅读

探索更多技术文章

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

全部文章 返回首页

「java」更多文章

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