在大数据处理领域,Apache Flink 以其卓越的流批一体化处理能力脱颖而出,成为众多企业构建实时数据应用的首选框架。本文将带领你迈出 Flink 学习的第一步,从基础概念入手,逐步引导你编写并运行第一个 Flink 程序 —— 经典的 WordCount,让你亲身感受 Flink 在实时数据流处理方面的强大魅力。
Flink 是一个分布式流批一体化开源平台,旨在对无界和有界数据流进行有状态计算。无界数据流是一种持续不断产生的数据,例如网站的实时访问日志、传感器的实时监测数据等;有界数据流则是在有限时间内产生的数据,像一份固定的历史订单数据集。Flink 通过统一的编程模型和运行时引擎,无缝处理这两种类型的数据,这是它区别于其他大数据框架的显著特性。
在编写 Flink 程序之前,需要搭建好开发环境。这里以 Maven 项目为例,在 Java 环境下进行开发。
确保本地安装了 Java 环境,并且配置了JAVA_HOME环境变量。可以通过在命令行中输入java -version来检查 Java 是否安装成功。
Maven 是一个项目管理工具,用于构建和管理 Java 项目。从 Maven 官网下载并解压安装包,然后配置MAVEN_HOME环境变量,将%MAVEN_HOME%\bin添加到系统的PATH变量中。在命令行中输入mvn -version验证 Maven 安装是否成功。
打开命令行,进入到合适的目录下,执行以下命令创建一个 Maven 项目:
mvn archetype:generate -DgroupId=com.example -DartifactId=flink -example -DarchetypeArtifactId=maven -archetype -quickstart -DinteractiveMode=false
这将创建一个名为flink - example的 Maven 项目,项目结构如下:
flink - example
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── App.java
│ └── resources
└── test
├── java
│ └── com
│ └── example
│ └── AppTest.java
└── resources
在项目的pom.xml文件中添加 Flink 相关依赖。这里以 Flink 1.14.2 版本为例,添加如下依赖:
org.apache.flink
flink - java
1.14.2
org.apache.flink
flink - streaming - java_2.12
1.14.2
org.apache.flink
flink - runtime_2.12
1.14.2
org.slf4j
slf4j - api
1.7.32
org.slf4j
slf4j - simple
1.7.32
这些依赖分别包含了 Flink 的核心 Java 库、流处理库、运行时库以及日志相关库。其中flink - streaming - java_2.12中的2.12表示 Scala 的版本,因为 Flink 是基于 Scala 开发的,这里使用的是与 Scala 2.12 兼容的版本。
WordCount 是大数据领域的经典入门程序,其功能是统计一段文本中每个单词出现的次数。在 Flink 中,我们可以使用流处理的方式来实现 WordCount,实时统计源源不断输入的文本流中的单词计数。
在src/main/java/com/example目录下创建一个新的 Java 类,命名为WordCount.java,编写如下代码:
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.util.Collector;
import java.util.Arrays;
public class WordCount {
public static void main(String[] args) throws Exception {
// 创建流执行环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// 从文件中读取数据作为数据源,这里假设文件名为input.txt,位于项目根目录下
DataStreamSource text = env.readTextFile("input.txt");
// 对读取到的文本进行处理
SingleOutputStreamOperator result = text
.flatMap((String line, Collector out) -> {
Arrays.stream(line.split(" ")).forEach(out::collect);
})
.map(word -> new WordWithCount(word, 1))
.keyBy(WordWithCount::getWord)
.sum("count");
// 打印结果
result.print();
// 执行任务
env.execute("WordCount Example");
}
// 定义一个POJO类用于存储单词及其计数
public static class WordWithCount {
private String word;
private int count;
public WordWithCount() {
}
public WordWithCount(String word, int count) {
this.word = word;
this.count = count;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@Override
public String toString() {
return "WordWithCount{" +
"word='" + word + '\'' +
", count=" + count +
'}';
}
}
}
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
StreamExecutionEnvironment是 Flink 流处理的入口点,通过getExecutionEnvironment方法获取一个运行时环境实例,它负责管理任务的执行和资源分配。
读取数据源:
DataStreamSource text = env.readTextFile("input.txt");
这里使用readTextFile方法从本地文件input.txt中读取数据,将文件中的每一行作为一个元素,创建一个DataStreamSource对象,它表示一个数据流的源头。
数据处理:
.flatMap((String line, Collector out) -> {
Arrays.stream(line.split(" ")).forEach(out::collect);
})
flatMap操作将输入的每一行文本按空格分割成多个单词,并将这些单词输出到下游。这里使用 Java 8 的Arrays.stream和forEach方法实现单词分割和输出。
.map(word -> new WordWithCount(word, 1))
map操作将每个单词映射为一个WordWithCount对象,其中单词作为word字段,初始计数为 1。
.keyBy(WordWithCount::getWord)
keyBy操作根据WordWithCount对象的word字段对数据流进行分组,相同单词的数据会被分到同一个组中,以便后续进行聚合操作。
.sum("count");
sum操作对每个组内的count字段进行求和,统计每个单词出现的总次数。
打印结果:
result.print();
print操作将处理后的结果打印到控制台,方便查看。在实际生产环境中,可能会将结果输出到其他存储系统,如 Kafka、HBase 等。
执行任务:
env.execute("WordCount Example");
execute方法触发任务的执行,参数"WordCount Example"是任务的名称,用于在 Flink 的 Web UI 中标识该任务。
在项目根目录下创建一个input.txt文件,输入一些文本内容,例如:
hello world
hello flink
flink is great
在命令行中进入项目目录,执行以下命令运行程序:
mvn clean package
java -cp target/flink - example - 1.0 - SNAPSHOT.jar com.example.WordCount
mvn clean package命令用于清理项目并打包成一个可执行的 JAR 文件,java -cp命令用于运行打包后的 JAR 文件,指定主类为com.example.WordCount。
运行成功后,控制台会输出每个单词及其出现的次数,类似如下结果:
WordWithCount{word='hello', count=2}
WordWithCount{word='world', count=1}
WordWithCount{word='flink', count=2}
WordWithCount{word='is', count=1}
WordWithCount{word='great', count=1}
通过这个简单的 WordCount 程序,你已经初步体验了 Flink 在实时数据流处理方面的基本操作流程。后续文章中,我们将深入探讨 Flink 的更多高级特性,如窗口操作、状态管理、Flink SQL 等,逐步提升你对 Flink 的掌握程度,构建更加复杂和强大的实时数据应用。