集群角色
- 客户端(Client):代码由客户端获取并做转换,之后提交给JobManger。
- JobManager 是 Flink 集群里的
“管事人”,对作业进行中央调度管理;而它获取到要执行的作业后,会进一步处理转换,然后分发任务给众多的TaskManager。 - TaskManager,就是真正
“干活的人”,数据的处理操作都是它们来做的。
❝
注意:Flink是一个非常灵活的处理框架,它支持多种不同的部署场景,还可以和不同的资源管理平台方便地集成。
Flink集群搭建
集群规划
| ip | hostname | 角色 |
|---|---|---|
| 192.168.40.131 | node01 | JobManager和TaskManager |
| 192.168.40.132 | node02 | TaskManager |
| 192.168.40.133 | node03 | TaskManager |
安装部署步骤
- 下载并解压安装包
# 下载
[hadoop@node01 opt]$ wget https://dist.apache.org/repos/dist/release/flink/flink-1.17.1/flink-1.17.1-bin-scala_2.12.tgz
# 解压
[hadoop@node01 opt]$ tar -zxvf flink-1.17.1-bin-scala_2.12.tgz -C /home/hadoop/opt/
- 修改集群配置
# 进入conf路径
[hadoop@node01 ~]$ cd /home/hadoop/opt/flink-1.17.1/conf
# 修改flink-conf.yaml文件,指定hadoop102节点服务器为JobManager
[hadoop@node01 conf]$ vim flink-conf.yaml
修改内容如下:
# JobManager节点地址.
jobmanager.rpc.address: node01
jobmanager.bind-host: 0.0.0.0
rest.address: node01
rest.bind-address: 0.0.0.0
# TaskManager节点地址.需要配置为当前机器名
taskmanager.bind-host: 0.0.0.0
taskmanager.host: node01
修改workers文件
# 指定node01、node02和node03为TaskManager
[hadoop@node01 conf]$ vim workers
# 修改如下内容
node01
node02
node03
修改masters文件
[hadoop@node01 conf]$ vim masters
# 修改如下内容
node01:8081
另外,在flink-conf.yaml文件中还可以对集群中的JobManager和TaskManager组件进行优化配置,主要配置项如下:
- jobmanager.memory.process.size:对JobManager进程可使用到的全部内存进行配置,包括JVM元空间和其他开销,
默认为1600M,可以根据集群规模进行适当调整。 - taskmanager.memory.process.size:对TaskManager进程可使用到的全部内存进行配置,包括JVM元空间和其他开销,
默认为1728M,可以根据集群规模进行适当调整。 - taskmanager.numberOfTaskSlots:对每个TaskManager能够分配的Slot数量进行配置,
默认为1,可根据TaskManager所在的机器能够提供给Flink的CPU数量决定。所谓Slot就是TaskManager中具体运行一个任务所分配的计算资源。 - parallelism.default:Flink任务执行的并行度,
默认为1。优先级低于代码中进行的并行度配置和任务提交时使用参数指定的并行度数量。
- 分发安装目录
# 配置修改完毕后,将Flink安装目录发给另外两个节点服务器
[hadoop@node01 opt]$ scp -r flink-1.17.1 hadoop@node02:/home/hadoop/opt/
[hadoop@node01 opt]$ scp -r flink-1.17.1 hadoop@node03:/home/hadoop/opt/
修改node02的taskmanager.host
[hadoop@node02 conf]$ cd /home/hadoop/opt/flink-1.17.1/conf
[hadoop@node02 conf]$ vim flink-conf.yaml
# 修改如下内容
# TaskManager节点地址.需要配置为当前机器名
taskmanager.host: node02
修改node03的taskmanager.host
[hadoop@node03 conf]$ cd /home/hadoop/opt/flink-1.17.1/conf
[hadoop@node03 conf]$ vim flink-conf.yaml
# 修改如下内容
# TaskManager节点地址.需要配置为当前机器名
taskmanager.host: node03
- 启动集群
在node01节点服务器上执行start-cluster.sh启动Flink集群
# 启动
[hadoop@node01 flink-1.17.1]$ bin/start-cluster.sh
# 查看进程情况
[hadoop@node01 flink-1.17.1]$ jpsall
=============== node01 ===============
31921 HistoryServer
16129 StandaloneSessionClusterEntrypoint
16504 TaskManagerRunner
=============== node02 ===============
7324 TaskManagerRunner
=============== node03 ===============
18729 TaskManagerRunner
[hadoop@node01 flink-1.17.1]$
访问WebUI
启动成功后,同样可以访问http://node01:8081对flink集群和任务进行监控管理。 这里可以明显看到,当前集群的TaskManager数量为3;由于默认每个TaskManager的Slot数量为1,所以总Slot数和可用Slot数都为3。
部署模式
在一些应用场景中,对于集群资源分配和占用的方式,可能会有特定的需求。Flink为各种场景提供了不同的部署模式,主要有以下三种:
- 会话模式(Session Mode)
- 单作业模式(Per-Job Mode)
- 应用模式(Application Mode)
它们的区别主要在于:集群的生命周期以及资源的分配方式;以及应用的main方法的执行位置——客户端(Client)还是JobManager。
会话模式(Session Mode)
会话模式其实最符合常规思维。我们需要先启动一个集群,保持一个会话,在这个会话中通过客户端提交作业。集群启动时所有资源就都已经确定,所以所有提交的作业会竞争集群中的资源。
❝
会话模式比较适合于单个规模小、执行时间短的大量作业。
单作业模式(Per-Job Mode)
会话模式因为资源共享会导致很多问题,所以为了更好地隔离资源,我们可以考虑 为每个提交的作业启动一个集群,这就是所谓的单作业(Per-Job)模式。
❝
作业完成后,集群就会关闭,所有资源也会释放。 这些特性使得单作业模式在生产环境运行更加稳定,所以是实际应用的首选模式。 需要注意的是,Flink本身无法直接这样运行,所以单作业模式一般需要借助一些资源管理框架来启动集群,比如YARN、Kubernetes(K8S)
应用模式(Application Mode)
会话模式和单作业模式下的应用代码都是在客户端上执行,然后由客户端提交给JobManager的。这种方式客户端需要占用大量网络带宽,去下载依赖和把二进制数据发送给JobManager;加上很多情况下我们提交作业用的是同一个客户端,就会加重客户端所在节点的资源消耗。
所以解决办法就是,我们不要客户端,直接把应用提交到JobManger上运行。而这也就代表着,我们需要为每一个提交的应用单独启动一个JobManager,也就是创建一个集群。这个JobManager只为执行这一个应用而存在,执行结束之后JobManager也就关闭了,这就是所谓的应用模式。
❝
应用模式与单作业模式,都是提交作业之后才创建集群;单作业模式是通过客户端来提交的,客户端解析出的每一个作业对应一个集群;而应用模式下,是直接由JobManager执行应用程序的。
因为在生产环境中绝大多数公司都使用 yarn 来管理资源,所以就以yarn提交方式进行重点介绍:
- yarn Session 模式:所有作业共享集群资源,隔离性差,JVM 负载瓶颈,main() 方法在客户端执行,适合执行时间短、频繁执行的短任务,集群中的所有作业只有一个 JobManager,另外 job 被随机分配给 TaskManager。
特点:yarn Session 模式需要先启动集群,然后再提交作业。
- yarn per job 模式:每个作业单独启动集群、隔离性好、JVM 负载均衡、mian() 方法在客户端执行。在 per job 模式下,每个 Job 都有一个JobManager,每个TaskManager 只有一个Job。
特点:一个任务(task)只会对应一个Jon,每提交一个作业都会根据自身情况单独向 yarn 申请资源,独享 Dispatcher 和 ResourceManager,按需接受资源申请,适合规模大、运行时间长的作业。
- yarn application 模式:mian() 方法在 JobManager中执行,入口点位于 ApplicationClusterEntryPoint,客户端只需要负责发起部署请求。
特点:极大缓解了客户端压力,避免资源成为一个瓶颈。
YARN运行模式
YARN上部署的过程是:客户端把Flink应用提交给Yarn的ResourceManager,Yarn的ResourceManager会向Yarn的NodeManager申请容器。在这些容器上,Flink会部署JobManager和TaskManager的实例,从而启动集群。Flink会根据运行在JobManger上的作业所需要的Slot数量动态分配TaskManager资源。
相关准备和配置
在将Flink任务部署至YARN集群之前,需要确认集群是否安装有Hadoop,保证Hadoop版本至少在2.2以上,并且集群中安装有HDFS服务。
- 配置环境变量,增加环境变量配置如下
$ [hadoop@node01 flink-1.17.1]$ sudo vim /etc/profile
# 添加内容
export HADOOP_HOME=/home/hadoop/opt/hadoop-3.3.5
export PATH=$HADOOP_HOME/bin:$PATH
export PATH=$HADOOP_HOME/sbin:$PATH
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export HADOOP_CLASSPATH=`hadoop classpath`
- 启动Hadoop集群,包括HDFS和YARN
[hadoop@node01 opt]$ cd /home/hadoop/opt/hadoop-3.3.5/sbin
[hadoop@node01 sbin]$ start-dfs.sh
[hadoop@node01 sbin]$ start-yarn.sh
会话模式部署
YARN的会话模式与独立集群略有不同,需要首先申请一个YARN会话(YARN Session)来启动Flink集群。具体步骤如下:
- 启动集群
- 启动Hadoop集群(HDFS、YARN)
- 执行脚本命令向YARN集群申请资源,开启一个YARN会话,启动Flink集群
bin/yarn-session.sh -nm test
❝
注意:Flink1.11.0版本以后不再使用-n参数和-s参数分别指定TaskManager数量和slot数量,YARN会按照需求动态分配TaskManager和slot。所以从这个意义上讲,YARN的会话模式也不会把集群资源固定,同样是动态分配的。
- 提交作业
- 命令行
bin/flink run -c ClassName xxx.jar - WebUI
http://node01:8088查看运行情况
单作业模式部署
在YARN环境中,由于有了外部平台做资源调度,所以我们也可以直接向YARN提交一个单独的作业,从而启动一个Flink集群。
- 执行命令提交作业。
bin/flink run -d -t yarn-per-job -c ClassName xxx.jar
注意:如果启动过程中报如下异常
Exception in thread “Thread-5” java.lang.IllegalStateException: Trying to access closed classloader. Please check if you store classloaders directly or indirectly in static fields. If the stacktrace suggests that the leak occurs in a third party library and cannot be fixed immediately, you can disable this check with the configuration ‘classloader.check-leaked-classloader’.
at org.apache.flink.runtime.execution.librarycache.FlinkUserCodeClassLoaders
解决办法:在flink的flink-conf.yaml配置文件中设置
cd /home/hadoop/opt/flink-1.17.1/conf/
vim flink-conf.yaml
classloader.check-leaked-classloader: false
使用命令行查看或取消作业
# 查看作业
[hadoop@node01 flink-1.17.1]$ bin/flink list -t yarn-per-job -Dyarn.application.id=application_XXXX_YY
# 取消作业
[hadoop@node01 flink-1.17.1]$ bin/flink cancel -t yarn-per-job -Dyarn.application.id=application_XXXX_YY <jobId>
这里的application_XXXX_YY是当前应用的ID,是作业的ID。注意如果取消作业,整个Flink集群也会停掉。
应用模式部署
应用模式同样非常简单,与单作业模式类似,直接执行flink run-application命令即可。
命令行提交
- 执行命令提交作业。
bin/flink run-application -t yarn-application -c ClassName xxx.jar
- 在命令行中查看或取消作业
[hadoop@node01 flink-1.17.1]$ bin/flink list -t yarn-application -Dyarn.application.id=application_XXXX_YY
[[hadoop@node01 flink-1.17.1]$ bin/flink cancel -t yarn-application -Dyarn.application.id=application_XXXX_YY <jobId>
上传HDFS提交
可以通过yarn.provided.lib.dirs配置选项指定位置,将flink的依赖上传到远程。
- 上传flink的lib和plugins到HDFS上
[hadoop@node01 flink-1.17.1]$ hadoop fs -mkdir /flink-dist
[hadoop@node01 flink-1.17.1]$ hadoop fs -put lib/ /flink-dist
[hadoop@node01 flink-1.17.1]$ hadoop fs -put plugins/ /flink-dist
- 上传自己的jar包到HDFS
[hadoop@node01 flink-1.17.1]$ hadoop fs -mkdir /flink-jars
[hadoop@node01 flink-1.17.1]$ hadoop fs -put xxx.jar /flink-jars
- 提交作业
[hadoop@node01 flink-1.17.1]$ bin/flink run-application -t yarn-application -Dyarn.provided.lib.dirs="hdfs://node01:8020/flink-dist" -c ClassName hdfs://hadoop102:8020/flink-jars/xxx.jar
这种方式下flink本身的依赖和用户jar可以预先上传到HDFS,而不需要单独发送到集群,这就使得作业提交更加轻量了。
历史服务器
运行 Flink job 的集群一旦停止,只能去 yarn 或本地磁盘上查看日志,不再可以查看作业挂掉之前的运行的 Web UI,很难清楚知道作业在挂的那一刻到底发生了什么。如果我们还没有 Metrics 监控的话,那么完全就只能通过日志去分析和定位问题了,所以如果能还原之前的 Web UI,我们可以通过 UI 发现和定位一些问题。
Flink提供了历史服务器,用来在相应的 Flink 集群关闭后查询已完成作业的统计信息。我们都知道只有当作业处于运行中的状态,才能够查看到相关的WebUI统计信息。通过 History Server 我们才能查询这些已完成作业的统计信息,无论是正常退出还是异常退出。
此外,它对外提供了 REST API,它接受 HTTP 请求并使用 JSON 数据进行响应。Flink 任务停止后,JobManager 会将已经完成任务的统计信息进行存档,History Server 进程则在任务停止后可以对任务统计信息进行查询。比如:最后一次的 Checkpoint、任务运行时的相关配置。
- 创建存储目录
hadoop fs -mkdir -p /logs/flink_hostory_log
- 在 flink-config.yaml中添加如下配置
jobmanager.archive.fs.dir: hdfs://node01:8020/logs/flink_hostory_log
historyserver.web.address: node01
historyserver.web.port: 8082
historyserver.archive.fs.dir: hdfs://node01:8020/logs/flink_hostory_log
historyserver.archive.fs.refresh-interval: 5000
- 启动/停止历史服务器
bin/historyserver.sh start
bin/historyserver.sh stop