flink bin/start-cluster.sh 帮我做成开机启动

flink ./bin/start-cluster.sh 帮我做成开机启动

可以。你是 tar.gz 方式安装 Flink,最简单稳妥的方式就是给 ./bin/start-cluster.sh 做一个 systemd 服务,让 Ubuntu 开机自动执行,同时关机时执行 stop-cluster.sh。

假设你的 Flink 安装目录是:

复制代码
/app/flink

运行 Flink 的 Linux 用户是:

复制代码
userroot

如果实际目录不同,把下面 /app/flink 替换成你的实际目录即可。

1. 先确认手动启动没问题

复制代码
cd /app/flink

./bin/start-cluster.sh

jps

正常应该能看到类似:

StandaloneSessionClusterEntrypoint TaskManagerRunner

然后先停掉:

复制代码
./bin/stop-cluster.sh

2. 创建 systemd 服务

执行:

复制代码
sudo vim /etc/systemd/system/flink.service

写入:

[Unit] Description=Apache Flink Standalone Cluster Documentation=https://flink.apache.org/ After=network-online.target Wants=network-online.target [Service] Type=oneshot User=userroot Group=userroot WorkingDirectory=/app/flink Environment="FLINK_HOME=/app/flink" Environment="JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64" ExecStart=/app/flink/bin/start-cluster.sh ExecStop=/app/flink/bin/stop-cluster.sh RemainAfterExit=yes TimeoutStartSec=120 TimeoutStopSec=120 [Install] WantedBy=multi-user.target

其中最需要确认的是:

User=userroot WorkingDirectory=/app/flink JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64

你的 Java 21 路径可以这样确认:

复制代码
readlink -f $(which java)

例如返回:

/usr/lib/jvm/java-21-openjdk-amd64/bin/java

那么:

Environment="JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64"

就是正确的。

3. 让 systemd 读取服务

复制代码
sudo systemctl daemon-reload

4. 设置开机启动

复制代码
sudo systemctl enable flink

会看到类似:

Created symlink /etc/systemd/system/multi-user.target.wants/flink.service

5. 现在直接测试启动

复制代码
sudo systemctl start flink

查看状态:

复制代码
sudo systemctl status flink

正常应该类似:

● flink.service - Apache Flink Standalone Cluster Loaded: loaded (/etc/systemd/system/flink.service; enabled) Active: active (exited)

这里的:

active (exited)

是正常的,不是 Flink 挂了。

因为:

复制代码
start-cluster.sh

本身只是负责把 JobManager 和 TaskManager 拉起来,然后脚本就退出了。

我们配置了:

Type=oneshot RemainAfterExit=yes

所以 systemd 会认为 Flink 服务仍然处于运行状态。

再执行:

复制代码
jps

应该能看到:

StandaloneSessionClusterEntrypoint TaskManagerRunner

还可以访问:

http://服务器IP:8081

确认 Flink Web UI 正常。

6. 测试 systemctl 停止

执行:

复制代码
sudo systemctl stop flink

然后:

复制代码
jps

Flink 的:

StandaloneSessionClusterEntrypoint TaskManagerRunner

应该消失。

再重新启动:

复制代码
sudo systemctl start flink

7. 最后测试真正的开机自启动

检查:

复制代码
sudo systemctl is-enabled flink

返回:

enabled

然后重启服务器:

复制代码
sudo reboot

服务器起来以后:

复制代码
systemctl status flink

以及:

复制代码
jps

如果看到 JobManager 和 TaskManager,就完成了。

你最终以后只需要记住这几个命令:

复制代码
# 启动
sudo systemctl start flink

# 停止
sudo systemctl stop flink

# 重启
sudo systemctl restart flink

# 查看状态
sudo systemctl status flink

# 开机启动
sudo systemctl enable flink

# 取消开机启动
sudo systemctl disable flink

对于你现在这种 tar.gz 单机 Standalone Flink 部署,我建议就用 Type=oneshot + RemainAfterExit=yes,不要直接把 start-cluster.sh 配成 Type=simple。 因为 start-cluster.sh 本身启动完 JobManager/TaskManager 后会退出,Type=simple 容易让 systemd 对进程生命周期产生错误判断。

/usr/local/flink 我的安装目录

那就把 Flink 目录统一改成 /usr/local/flink。

创建服务文件:

复制代码
sudo vim /etc/systemd/system/flink.service

内容改成:

[Unit] Description=Apache Flink Standalone Cluster Documentation=https://flink.apache.org/ After=network-online.target Wants=network-online.target [Service] Type=oneshot User=userroot Group=userroot WorkingDirectory=/usr/local/flink Environment="FLINK_HOME=/usr/local/flink" Environment="JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64" ExecStart=/usr/local/flink/bin/start-cluster.sh ExecStop=/usr/local/flink/bin/stop-cluster.sh RemainAfterExit=yes TimeoutStartSec=120 TimeoutStopSec=120 [Install] WantedBy=multi-user.target

先确认 Java 路径:

复制代码
readlink -f $(which java)

如果返回例如:

/usr/lib/jvm/java-21-openjdk-amd64/bin/java

那上面的:

Environment="JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64"

就是对的。

然后依次执行:

复制代码
sudo systemctl daemon-reload

sudo systemctl enable flink

sudo systemctl start flink

sudo systemctl status flink

再确认 Flink 进程:

复制代码
jps

正常应该有类似:

StandaloneSessionClusterEntrypoint TaskManagerRunner

也可以看 8081 是否起来:

复制代码
ss -lntp | grep 8081

以后启动/停止就不用再执行:

复制代码
/usr/local/flink/bin/start-cluster.sh

直接:

复制代码
sudo systemctl start flink
sudo systemctl stop flink
sudo systemctl restart flink
sudo systemctl status flink

还有一个地方建议你先确认一下:/usr/local/flink 是谁拥有的。

执行:

复制代码
ls -ld /usr/local/flink

如果显示类似:

drwxr-xr-x ... userroot userroot ... /usr/local/flink

那么:

User=userroot Group=userroot

就可以直接用。

如果显示的是其他用户,把结果发我,我可以直接帮你把 flink.service 调整到完全匹配你这台服务器。

User=wenhaoran Group=wenhaoran

那就把 systemd 服务里的运行用户改成 wenhaoran。

/etc/systemd/system/flink.service 建议最终写成:

[Unit] Description=Apache Flink Standalone Cluster Documentation=https://flink.apache.org/ After=network-online.target Wants=network-online.target [Service] Type=oneshot User=wenhaoran Group=wenhaoran WorkingDirectory=/usr/local/flink Environment="FLINK_HOME=/usr/local/flink" Environment="JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64" ExecStart=/usr/local/flink/bin/start-cluster.sh ExecStop=/usr/local/flink/bin/stop-cluster.sh RemainAfterExit=yes TimeoutStartSec=120 TimeoutStopSec=120 [Install] WantedBy=multi-user.target

然后执行:

复制代码
sudo systemctl daemon-reload

sudo systemctl enable flink

sudo systemctl start flink

sudo systemctl status flink

再检查:

复制代码
jps

正常应该看到类似:

StandaloneSessionClusterEntrypoint TaskManagerRunner

最好再确认一下 /usr/local/flink 的权限:

复制代码
ls -ld /usr/local/flink

理想情况是类似:

drwxr-xr-x ... wenhaoran wenhaoran ... /usr/local/flink

如果不是,可以改:

复制代码
sudo chown -R wenhaoran:wenhaoran /usr/local/flink

另外,Java 路径一定要确认一下:

复制代码
readlink -f $(which java)

如果结果不是:

/usr/lib/jvm/java-21-openjdk-amd64/bin/java

那 flink.service 里的 JAVA_HOME 要跟着改。

flink 我是新手 task 和 job 是什么关系

可以把 Flink 里的关系先记成一句话:

Job 是整个作业,Task 是这个作业真正跑起来后的执行单元。

结合你现在的水务实时预警项目会更容易理解。

假设你的代码大概是:

复制代码
env.fromSource(kafkaSource, ...)
   .map(...)
   .keyBy(...)
   .process(...)
   .sinkTo(...);

env.execute("WaterAlarmJob");

这里执行以后,Flink 会提交一个 Job:

WaterAlarmJob

它代表"这一整套实时计算流程"。

可以理解成:

一个 Job | +-- Kafka Source | +-- Map | +-- KeyBy | +-- Process | +-- Sink

这些步骤叫 Operator(算子)。

但是 Flink 真正运行时,并不是简单地"一个算子 = 一个 Task"。它会根据并行度,把算子拆成多个并行执行实例,也就是 Subtask。

比如你设置:

复制代码
env.setParallelism(2);

那么 Kafka Source 可能有:

Source Subtask 0 Source Subtask 1

Process 也可能有:

Process Subtask 0 Process Subtask 1

Sink 也可能有:

Sink Subtask 0 Sink Subtask 1

所以可以把关系理解为:

Job | +-- Operator | | | +-- Subtask 0 | +-- Subtask 1 | +-- Operator | +-- Subtask 0 +-- Subtask 1

其中这些 Subtask 才是实际在 TaskManager 上运行的执行实例。

再用你比较熟悉的 Java/Spring 思路类比:

Job ≈ 一个完整业务流程 Operator ≈ 业务流程中的一个处理步骤 Subtask ≈ 这个处理步骤的一个并发执行实例

比如水务预警:

Kafka读取点位 ↓ JSON解析 ↓ 按 deviceId / pointCode 分组 ↓ 规则判断 ↓ 生成告警 ↓ 写数据库 / Kafka

这一整条:

WaterAlarmJob

是一个 Job。

其中:

Kafka Source 规则判断 Alarm Sink

是不同的 Operator。

如果规则判断并行度是 4:

规则判断 ├── Subtask 0 ├── Subtask 1 ├── Subtask 2 └── Subtask 3

这意味着可以同时有 4 个并行执行实例处理数据。


还有一个特别容易混淆的概念:TaskManager。

关系大概是:

Flink Cluster JobManager | | 调度 WaterAlarmJob | v TaskManager | +-- Slot | +-- Task / Subtask | +-- Slot +-- Task / Subtask

你之前遇到过:

Task Managers: 0 Total Task Slots: 0 Available Task Slots: 0

然后 Job 报:

NoResourceAvailableException Could not acquire the minimum required resources

本质就是:

Job 已经提交了 ↓ JobManager 准备调度 Task ↓ 但是没有 TaskManager ↓ 没有 Slot ↓ Task 没地方执行 ↓ Job 启动失败

这个关系非常重要。

再比如你现在启动:

复制代码
/usr/local/flink/bin/start-cluster.sh

在 standalone 模式下一般会启动:

JobManager TaskManager

JobManager 是"大脑",负责:

接收 Job 拆分执行任务 调度 Task 失败恢复 Checkpoint 协调

TaskManager 是"工人",负责:

真正执行 Task/Subtask


Parallelism 和 Task 的关系

你之前也问过 parallelism。

比如:

复制代码
env.setParallelism(4);

它不是说:

启动 4 个 Job

而是说:

一个 Job 中的算子,默认允许拆成 4 个并行 Subtask。

例如:

WaterAlarmJob

只有 1 个 Job。

但规则计算可能变成:

Rule Process ├── subtask 0 ├── subtask 1 ├── subtask 2 └── subtask 3

假设 Kafka 里:

device001 device002 device003 device004 device005 ...

经过:

复制代码
.keyBy(PointValue::deviceId)

之后,Flink 会把不同 key 分发给不同 subtask:

Subtask 0 device001 device005 Subtask 1 device002 device006 Subtask 2 device003 device007 Subtask 3 device004 device008

这样多个设备的数据就能并行处理。

但同一个 key,例如:

device001

通常会一直进入同一个下游 Keyed Operator 的 subtask,这样状态才不会乱。

对你的水务规则判断特别重要,比如:

A_Phase_Voltage 连续 5 次 > 250 才报警

如果同一个点位的数据被随机扔到不同 Task:

Task 1 收到第1、3、5条 Task 2 收到第2、4条

那"连续 5 次"就没法正确统计。

所以通常会:

复制代码
.keyBy(data -> data.getDeviceId() + ":" + data.getPointCode())

然后:

同一个 device + point ↓ 始终去同一个 subtask ↓ 这个 subtask 保存状态 ↓ 连续次数才能正确计算

这也是 Flink 的核心思想之一。


你目前作为新手,建议先记住这 5 个词的关系:

Job 整个 Flink 程序/作业 Operator Job 里面的计算步骤 例如 Source、Map、Process、Sink Parallelism 一个 Operator 有多少个并行执行实例 Subtask Operator 的某一个并行实例 TaskManager 真正运行这些 Subtask 的 JVM 进程

画成一张图就是:

Flink Cluster | +----------+----------+ | | JobManager TaskManager | | | +-- Slot | | | | | +-- Subtask | | | +-- Slot | | | +-- Subtask | +-- WaterAlarmJob | +-- Kafka Source | +-- Rule Process | +-- Alarm Sink

对于你现在这个项目,最值得继续理解的下一层其实是:

Job → Operator → Task/Subtask → Slot → TaskManager → Parallelism

把这几个关系搞清楚后,你再看 Flink Web UI 里的 Jobs / TaskManagers / Task Slots / Parallelism,基本就不会迷糊了。

相关推荐
Sarvartha1 小时前
Lambda 表达式和函数式接口
java·开发语言
小白学大数据1 小时前
拼多多反爬对抗实战:Scrapy 中间件化采集架构解析
开发语言·scrapy·中间件·架构
学逆向的2 小时前
win32注入代码
开发语言·网络安全·api·win32
MoRanzhi12032 小时前
第 3 篇 · 数据清洗与特征工程:从问题判定到特征构建
python·pandas·数据清洗·特征工程·缺失值处理·异常值检测·特征编码
Sarvartha2 小时前
内部类知识
java·开发语言
刘科领2 小时前
使用ollama & openweb-ui 本地搭建自己的AI
人工智能·python·ui·ai
专业程序开发源2 小时前
flask家电故障预测系统92491-计算机课程设计/毕业设计
vscode·python·sql·算法·flask·课程设计
夜雪一千2 小时前
Python 生成模拟地址数据:Faker之外的备选库
网络·windows·python
半亩码田3 小时前
C#转Python第4.8篇:正则表达式:Python re 模块 vs C# System.Text.RegularExpressions
python·正则表达式·c#