一、Flink ML 简介:为什么要在 Flink 上做机器学习?
简单理解:
- Flink :负责数据处理引擎------高吞吐、低延迟的流批统一引擎。
- Flink ML :是在 Flink 之上的机器学习库,提供了算法、Pipeline API 等能力。
使用 Flink ML 有两个典型优势:
-
数据就地训练与预测
你本来就用 Flink 做实时 ETL、流式计算,现在可以在同一套引擎上完成训练和预测,避免频繁导入导出数据。
-
天然适配流式场景
很多业务并不是"离线跑一个模型就完了",而是需要增量更新模型、实时预测、边流式处理边打标签,这类场景 Flink ML 非常适合。
本文的目标是先把"跑通"这件事搞定,后面再谈如何在真实业务中"用好"。
二、环境准备:Java 是前提
Flink 运行在 JVM 上,所以首先要确保本地已经安装了 Java 8 或更高版本。
在终端里执行:
bash
java -version
正常情况下会输出类似:
text
java version "1.8.0_xxx"
Java(TM) SE Runtime Environment (build 1.8.0_xxx)
Java HotSpot(TM) 64-Bit Server VM (build 25.xxx-bxx, mixed mode)
如果提示 command not found 或版本过低,就需要先安装/升级 JDK,这里不展开。
三、下载并解压 Flink
本篇示例使用的是 Flink 1.17(你也可以用其他兼容版本,但建议先按官方 Quick Start 来)。
- 从官网或镜像下载 Flink 1.17 安装包(通常是
flink-1.17.x-bin-scala_2.12.tgz这种名字)。 - 在终端中进入下载目录,执行解压命令:
bash
tar -xzf flink-*.tgz
解压完成后,你会得到一个类似 flink-1.17.x/ 的目录,这就是本地 Flink 安装目录。
四、配置 FLINK_HOME 环境变量
为了后面操作方便,我们通常会配置一个环境变量 FLINK_HOME 指向 Flink 的安装目录。
进入刚才解压出来的目录:
bash
cd ${path_to_flink} # 比如 cd ~/apps/flink-1.17.0
export FLINK_HOME=`pwd`
此时:
$FLINK_HOME就代表 Flink 根目录$FLINK_HOME/bin下面就是start-cluster.sh、flink等脚本
建议 :
如果你打算长期使用 Flink,可以把
export FLINK_HOME=/your/flink/path和
export PATH=$PATH:$FLINK_HOME/bin写入
~/.bashrc或~/.zshrc,免得每次都手动 export。
五、为 Flink 添加 Flink ML 库
Flink 自身并不自带 Flink ML 的 jar,因此需要我们手动将 Flink ML 的依赖 jar 拷贝到 Flink 的 lib 目录中。
1. 下载 Flink ML Python 源码包
官方 Quick Start 的做法是下载一个类似 apache-flink-ml-*.tar.gz 的压缩包,这里面包含了 Flink ML 的 jar 文件(虽然叫 Python source,但内含 Java jar)。
2. 解压 Flink ML 包
在终端中执行:
bash
tar -xzf apache-flink-ml*.tar.gz
解压后会出现一个类似 apache-flink-ml-*/ 的目录。
3. 拷贝 jar 到 Flink 的 lib 目录
继续执行:
bash
cp apache-flink-ml-*/deps/lib/* $FLINK_HOME/lib/
这一步的含义是:
把 Flink ML 依赖目录下的所有 jar 文件,复制到 Flink 的 lib 目录里。
为什么要拷到
$FLINK_HOME/lib?因为 Flink 的 Standalone 集群在启动时,会自动加载
lib/下的所有 jar 作为全局依赖 。这样你提交作业时,只需要提供作业自身的 jar,公共库(如 Flink ML)已经在集群侧可见。
六、启动本地 Flink Standalone 集群
一切准备就绪之后,就可以在本地拉起一个小型的 Flink 集群(实际上是一个 JobManager + 若干 TaskManager)。
在终端执行:
bash
$FLINK_HOME/bin/start-cluster.sh
如果成功,你会看到类似:
text
Starting cluster.
Starting standalonesession daemon on host ...
Starting taskexecutor daemon on host ...
接着,在浏览器中访问:
text
http://localhost:8081
如果看到 Flink 的 Web UI 控制台,说明集群已经成功启动,可以接受作业了。
在 Web UI 中你可以看到:
- Overview:集群概况
- Running Jobs:正在运行的作业
- TaskManagers:工作节点信息等
七、提交并运行 Flink ML 示例:KMeans 聚类
Flink ML 官方提供了一些示例作业,我们可以先跑一个最经典的 KMeansExample。
在终端执行:
bash
$FLINK_HOME/bin/flink run \
-c org.apache.flink.ml.examples.clustering.KMeansExample \
$FLINK_HOME/lib/flink-ml-examples*.jar
这条命令可以拆解一下理解:
-
$FLINK_HOME/bin/flink run:使用 Flink 提交一个作业 -
-c org.apache.flink.ml.examples.clustering.KMeansExample:- 指定 main class(作业入口类)
-
$FLINK_HOME/lib/flink-ml-examples*.jar:- 指定示例 jar 的路径(通常在 Flink ML 的 examples 模块里)
如果命令执行后没有报错,可以回到 Flink Web UI,在 Jobs 页面就能看到这个示例作业的运行记录。
八、示例输出解析:KMeans 把点分成了两簇
示例作业执行成功后,你会在终端看到类似输出:
text
Features: [9.0, 0.0] Cluster ID: 1
Features: [0.3, 0.0] Cluster ID: 0
Features: [0.0, 0.3] Cluster ID: 0
Features: [9.6, 0.0] Cluster ID: 1
Features: [0.0, 0.0] Cluster ID: 0
Features: [9.0, 0.6] Cluster ID: 1
这些内容大致含义是:
- Features :样本的特征向量,这里是二维点
[x, y] - Cluster ID:KMeans 训练的结果,将这些点分配到不同的聚类中(例如 0、1)
从数据上可以看出:
-
[0.3, 0.0]、[0.0, 0.3]、[0.0, 0.0]都被归为Cluster ID: 0------这一簇大概是"靠近原点的一堆点"
-
[9.0, 0.0]、[9.6, 0.0]、[9.0, 0.6]都被归为Cluster ID: 1------这一簇则是"靠近 x=9 左右的一堆点"
也就是说,示例里构造了一些二维数据点,然后使用 KMeans 算法将它们自动分成了两类。
Flink ML 完成的工作大致包括:
- 定义数据源(这些样本点)
- 构建 KMeans 算法的训练 Pipeline
- 在 Flink 上执行训练
- 使用训练好的模型对样本进行预测
- 将「特征向量 + 聚类结果」打印出来
这就是一个完整的"训练 + 预测"的最小闭环,虽然数据很简单,但流程非常典型。
九、停止 Flink 集群
示例作业跑完之后,如果你暂时不再使用 Flink,可以关闭本地集群:
bash
$FLINK_HOME/bin/stop-cluster.sh
执行成功后 JobManager 和 TaskManager 进程会退出,Web UI 也会无法访问。
十、常见问题与排查思路(可选阅读)
第一次上手时,可能会遇到一些小坑,这里简单列出一些常见问题和排查方式:
-
java: command not found或version太低- 检查是否安装 JDK
- 确认
JAVA_HOME和PATH配置正确
-
start-cluster.sh报错- 查看
$FLINK_HOME/log下的日志(standalonesession*.log、taskexecutor*.log) - 检查端口是否被占用(默认 8081)
- 查看
-
执行示例时提示类找不到(ClassNotFound)
- 确认
flink-ml-examples*.jar真的在$FLINK_HOME/lib/ - 确认
-c org.apache.flink.ml.examples.clustering.KMeansExample类名拼写无误
- 确认
-
Web UI 打不开
- 检查进程:
ps aux | grep flink - 检查防火墙设置或端口占用问题
- 检查进程: