Flink学习2-安装、启动和配置
Flink系列文章
摘要
本篇文章主要讲解Flink下载、安装和启动的步骤。
1 下载
关于下载的更多信息可参考Flink官网
如果是用的MacOS X,可以直接用Homebrew安装:
brew install apache-flink
当前最新稳定的版本是v1.6.1。Flink可以不依赖Hadoop,但我们环境中要把Flink跑在Yarn上,所以需要下载Flink With Hadoop的版本的tgz包:
2 安装和配置
2.1 安装
只需直接解压即可
$ tar -zxvf flink-1.6.1-bin-hadoop27-scala_2.11.tgz
$ cd flink-1.6.1
$ bin/flink --version
Version: 1.6.1, Commit ID: 23e2636
懒人可以设置一个PATH,以便以后在任意路径可以直接使用flink命令:
$ vim ~/.bash_profile
# 增加以下内容
PATH="/Users/chengc/cc/apps/flink-1.6.1/bin:${PATH}"
export PATH
保存后可以试试看:
$ flink -v
Version: 1.6.1, Commit ID: 23e2636
2.2 配置
配置项应写入$FLINK_HOME/conf/flink-conf.yaml
文件或启动命令中使用类似-yD env.java.opts.jobmanager="-XX:+PrintGCDetails"
方式配置
2.2.1 启动配置
2.2.2.1 Job并行度
-
taskmanager.numberOfTaskSlots
指定一个TaskManager的Slot个数,默认为1。该值推荐设为TM CPU核心数或一半。每个slot可以运行一个task或pipeline。该选项不同设置分析:
- 该选项设置大于1时,可使得TM上的slot们共享JVM、应用库、网络等资源,利用多CPU核心,提高资源利用率,但内存会被分隔为slot数量份。
- 而如果设置为1,则提供了最高的task-slot资源隔离级别。
-
parallelism.default
当没有指定parallelism
时的默认并行度,默认值为1。
Flink on YARN时,TaskManagers个数 = Job中的最大并行度 / 每个TaskManager分配的Slot数
。
也就是说TM数量由Flink根据你的Job情况自动推算,-yn
启动参数失效了。
一个Flink Job生成T执行计划时关于分为多个Task或Pipeline,Task可以由多线程并发执行,每个线程处理Task输入数据的一个子集,并发线程数就是Parallelism
(并行度)。
我们可以有多种方法设置并行度,优先级从高到低为:
- 算子级别
val text: DataStream[String] = env.socketTextStream(hostname, port, '\n') text.flatMap { w => w.split("\\s") }.setParallelism(2)
- ExecutionEnvironment 级别
val bsEnv = StreamExecutionEnvironment.getExecutionEnvironment bsEnv.setParallelism(1)
- 提交时命令行指定
将job并行度设为40bin/flink run -m yarn-cluster ... -p 40 ...
- 配置文件(
flink-conf.yaml
)级别
parallelism.default: 4
2.2.2 内存配置
参考:
3 Standalone模式Flink集群启动
3.1 Flink集群的启动
通过简单命令就能在本地启动一个Flink集群
$ ./bin/start-cluster.sh
Starting cluster.
Starting standalonesession daemon on host chengcdeMacBook-Pro.local.
Starting taskexecutor daemon on host chengcdeMacBook-Pro.local.
看到以上信息代表Flink启动成功,我们可以通过jps来看看启动了哪些进程:
$ jps
70673 TaskManagerRunner
70261 StandaloneSessionClusterEntrypoint
70678 Jps
69647 Launcher
69646 NailgunRunner
可以看到分别启动了好几个Flink的重要组件,如果你看了第一章应该了解他们的作用。
3.2 Flink监控页面
我们可以通过访问http://localhost:8081看看效果:
可以从flink的web界面上看到现在运行了一个Task Manager实例。
3.3 Flink集群日志
还可以通过查看日志看到flink服务器正常启动:
tail -100f log/flink-*-standalonesession-*.log
3.4 Flink集群的停止
通过简单命令就能停止Flink集群:
$ ./bin/stop-cluster.sh
4 Standalone模式示例
4.1 Maven
4.1.1 骨架构建
Scala版本官网构建初始Flink工程例子:Project Template for Scala
构建过程如遇问题可参考Flink Maven archetype:generate
用Maven骨架构建Flink初始工程需要使用Maven 3.0.4+
以及Java 8.x
,然后有以下两种方式构建初始工程:
- mvn archetype:generate方式
此方式或让你输入工程的groupId、artifactId、version等信息,最后得到构建好的初始工程,名字就是输入的artifactId。mvn archetype:generate \ -DarchetypeGroupId=org.apache.flink \ -DarchetypeArtifactId=flink-quickstart-scala \ -DarchetypeVersion=1.9.0
- 调用quickstart远程脚本
此方法得到的工程名为$ curl https://flink.apache.org/q/quickstart-scala.sh | bash -s 1.9.0
quickstart
。
以上两个方法得到的工程初始文件情况类似如下:
$ tree chengc-flink-demo/
chengc-flink-demo/
├── pom.xml
└── src
└── main
├── resources
│ └── log4j.properties
└── scala
└── com
└── chengc
└── flink
├── BatchJob.scala
└── StreamingJob.scala
BatchJob和StreamingJob分别表示DataSet批处理、DataStream流处理项目,他们各自的main方法里有一些基本方法和注释。
以上步骤执行完后,可以使用mvn clean package
打包。如果要改变打出的包的main-class,请修改pom中maven-shade-plugin的<mainClass>
。
4.1.2 Maven
以下的依赖分为Java版和Scala版。这些依赖包括Flink本地运行环境所以可以在本地运行调试我们的Flink代码。
4.1.2.1 For Java
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-java</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java_2.11</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-clients_2.11</artifactId>
<version>1.6.1</version>
</dependency>
4.1.2.2 For Scala
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-scala_2.11</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-scala_2.11</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-clients_2.11</artifactId>
<version>1.6.1</version>
</dependency>
4.2 Code
4.2.1 Java
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.functions.ReduceFunction;
import org.apache.flink.api.java.utils.ParameterTool;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.util.Collector;
/**
* Implements a streaming windowed version of the "WordCount" program.
*
* <p>This program connects to a server socket and reads strings from the socket.
* The easiest way to try this out is to open a text server (at port 12345)
* using the <i>netcat</i> tool via
* <pre>
* nc -l 12345
* </pre>
* and run this example with the hostname and the port as arguments.
*/
@SuppressWarnings("serial")
public class SocketWindowWordCount {
public static void main(String[] args) throws Exception {
// the host and the port to connect to
final String hostname;
final int port;
try {
final ParameterTool params = ParameterTool.fromArgs(args);
hostname = params.has("hostname") ? params.get("hostname") : "localhost";
port = params.getInt("port");
} catch (Exception e) {
System.err.println("No port specified. Please run 'SocketWindowWordCount " +
"--hostname <hostname> --port <port>', where hostname (localhost by default) " +
"and port is the address of the text server");
System.err.println("To start a simple text server, run 'netcat -l <port>' and " +
"type the input text into the command line");
return;
}
// get the execution environment
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// get input data by connecting to the socket
DataStream<String> text = env.socketTextStream(hostname, port, "\n");
// parse the data, group it, window it, and aggregate the counts
DataStream<WordWithCount> windowCounts = text
.flatMap(new FlatMapFunction<String, WordWithCount>() {
@Override
public void flatMap(String value, Collector<WordWithCount> out) {
for (String word : value.split("\\s")) {
out.collect(new WordWithCount(word, 1L));
}
}
})
.keyBy("word")
.timeWindow(Time.seconds(5))
.reduce(new ReduceFunction<WordWithCount>() {
@Override
public WordWithCount reduce(WordWithCount a, WordWithCount b) {
return new WordWithCount(a.word, a.count + b.count);
}
});
// print the results with a single thread, rather than in parallel
windowCounts.print().setParallelism(1);
env.execute("Socket Window WordCount");
}
// ------------------------------------------------------------------------
/**
* Data type for words with count.
*/
public static class WordWithCount {
public String word;
public long count;
public WordWithCount() {}
public WordWithCount(String word, long count) {
this.word = word;
this.count = count;
}
@Override
public String toString() {
return word + " : " + count;
}
}
}
4.2.2 scala
import org.apache.flink.api.java.utils.ParameterTool
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.time.Time
/**
* Implements a streaming windowed version of the "WordCount" program.
*
* This program connects to a server socket and reads strings from the socket.
* The easiest way to try this out is to open a text sever (at port 12345)
* using the ''netcat'' tool via
* {{{
* nc -l 12345
* }}}
* and run this example with the hostname and the port as arguments..
*/
object SocketWindowWordCount {
/** Main program method */
def main(args: Array[String]) : Unit = {
// the host and the port to connect to
var hostname: String = "localhost"
var port: Int = 0
try {
val params = ParameterTool.fromArgs(args)
hostname = if (params.has("hostname")) params.get("hostname") else "localhost"
port = params.getInt("port")
} catch {
case e: Exception => {
System.err.println("No port specified. Please run 'SocketWindowWordCount " +
"--hostname <hostname> --port <port>', where hostname (localhost by default) and port " +
"is the address of the text server")
System.err.println("To start a simple text server, run 'netcat -l <port>' " +
"and type the input text into the command line")
return
}
}
// get the execution environment
val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
// get input data by connecting to the socket
val text: DataStream[String] = env.socketTextStream(hostname, port, '\n')
// parse the data, group it, window it, and aggregate the counts
val windowCounts = text
.flatMap { w => w.split("\\s") }
.map { w => WordWithCount(w, 1) }
.keyBy("word")
.timeWindow(Time.seconds(5))
.sum("count")
// print the results with a single thread, rather than in parallel
windowCounts.print().setParallelism(1)
env.execute("Socket Window WordCount")
}
/** Data type for words with count */
case class WordWithCount(word: String, count: Long)
}
4.3 打包
将文件打包为jar
flink-demo-1.0-SNAPSHOT-jar-with-dependencies.jar
4.4 启动示例程序
以上代码所写的程序功能是从socket
中读取文本,然后每隔5秒打印出每个单词在当前时间往前推5秒的时间窗口内的出现次数。
4.4.1 启动netcat
在9999
端口启动本地netcat服务:
$ nc -l 9999
4.4.2 提交Flink应用
$ flink run /Users/chengc/cc/work/projects/flink-demo/target/SocketWindowWordCount-jar-with-dependencies.jar --port 9999
# 看到控制台输出以下信息代表任务提交成功
Starting execution of program
现在我们看看前面提到过的flink web界面:
点击这行job信息能看到job详情页:
4.4.3 测试Flink应用
通过以上步骤我们建立了Flink应用和9999端口的关系,现在我们试试再nc
界面输入一些字符串:
$ nc -lk 9999
i am a chinese
who are you
how do you do
how do you do
与此同时,我们使用tailf
查看flink 应用的输出:
$ tail -f log/flink-*-taskexecutor-*.out
i : 1
chine : 1
a : 1
am : 1
who : 1
you : 1
are : 1
how : 2
you : 2
do : 4
可以看到 ,示例程序以翻滚窗口(tumbling window)的形式每隔5秒将前5秒的数据进行了字符统计。
5 Flink on Yarn
先决条件:
- Hadoop 2.4+
可参考:
5.1 配置HADOOP/YARN环境变量
提交Flink任务时,所在机器必须要至少设置环境变量YARN_CONF_DIR
、HADOOP_CONF_DIR
、HADOOP_CONF_PATH
中的一个,才能读取YARN和HDFS的配置信息(会按三者从左到右的顺序读取,只要发现一个就开始读取。如果没有正确设置,会尝试使用HADOOP_HOME/etc/hadoop
),否则提交任务会失败。
5.2 关于执行脚本参数
5.2.1 $FLINK_HOME/bin/yarn-session.sh
yarn-session.sh
主要是用来在Yarn上启动常驻Flink集群。
参数说明如下:
必填
-n,--container <arg> 分配多少个yarn container (=TaskManager的数量)
可选
-D <property=value> 设置属性值
-d,--detached Start detached,类似于spark的yarn-cluster模式,既不依赖于本地Yarn Session启动进程。
-h,--help yarn session帮助
-id,--applicationId <arg> 依附到某个指定yarn session来提交job
-j,--jar <arg> flink jar路径
-jm,--jobManagerMemory <arg> JobManager的Container内存 [默认是MB]
-m,--jobmanager <arg> 当需要连接不同于configuration中的那个JobManager(master)时使用该参数指定。
-nl,--nodeLabel <arg> 当需要flink job仅运行在基于标签的Yarn NM node上时使用该参数
-nm,--name 设置该job在yarn上运行时的application name
-q,--query 显示yarn中可用的资源 (内存, cpu)
-qu,--queue <arg> 指定要提交到的Yarn队列.
-s,--slots <arg> 每个TaskManager使用的slot数。推荐设为每个机器的CPU数。
-t,--ship <arg> 上传指定的相对路径的本地文件到Flink集群,程序中读取文件也使用相对路径
-tm,--taskManagerMemory <arg> 每个TaskManager的Container内存 [默认是MB]
-yd,--yarndetached If present, runs the job in detached mode (deprecated; use non-YARN specific option instead)
-z,--zookeeperNamespace <arg> 针对HA模式时,在zookeeper上用来创建子路径的NameSpace
5.2.2 $FLINK_HOME/bin/flink
5.2.2.1 概述
可参考:
该方法可加很多Action参数:
- run
用来编译、运行程序 - info
展示优化后JSON格式的程序执行计划 - list
展示正在运行的和调度的程序 - stop
停止一个正在运行的流式程序 - cancel
撤销一个正在运行的程序 - savepoint
触发正在运行的作业的savepoint或处置现有的savepoint。 - modify
修改一个运行中的任务参数,如改变并行度等
5.2.2.2 run
-c,--class <classname> 当jar包内没有用manifest指定运行的class时,需要使用该选项来指定主类(既包括`main`或`getPlan`方法的类)
-C,--classpath <url> Adds a URL to each user code
classloader on all nodes in the
cluster. The paths must specify a
protocol (e.g. file://) and be
accessible on all nodes (e.g. by means
of a NFS share). You can use this
option multiple times for specifying
more than one URL. The protocol must
be supported by the {@link
java.net.URLClassLoader}.
-d,--detached 使用detached mode运行job,此时client会将flink job体较到固定的Flink集群运行。这种模式不能使用flink命令停止yarn-session,需要使用yarn application -kill <appId>
-n,--allowNonRestoredState 允许跳过无法还原的保存点状态。
如果在触发保存点时从程序中删除了一部分运算符,则需要允许此操作。
-p,--parallelism <parallelism> 运行job的并行度,配置了就会覆盖configuration内的默认值(parallelism.default: 1)。
-q,--sysoutLogging If present, suppress logging output to
standard out.
-s,--fromSavepoint <savepointPath> 保存点恢复job来源路径
(如 hdfs:///flink/savepoint-1537)
yarn-cluster mode可选项:
-d,--detached 使用detached mode运行job,此时client会将flink job体较到固定的Flink集群运行。
这种模式不能使用flink命令停止yarn-session,需要使用yarn application -kill <appId>
-m,--jobmanager <arg> 当需要连接不同于configuration中的那个JobManager(master)时使用该参数指定。
-yD <property=value> 设置属性值
-yd,--yarndetached (deprecated; use non-YARN
specific option instead)If present, runs the job in detached
mode
-yh,--yarnhelp Help for the Yarn session CLI.
-yid,--yarnapplicationId <arg> Attach to running YARN session
-yj,--yarnjar <arg> Path to Flink jar file
-yjm,--yarnjobManagerMemory <arg> Memory for JobManager Container with
optional unit (default: MB)
-yn,--yarncontainer <arg> 分配多少个yarn container (=TaskManager的数量)
-ynl,--yarnnodeLabel <arg> Specify YARN node label for the YARN
application
-ynm,--yarnname <arg> Set a custom name for the application
on YARN
-yq,--yarnquery Display available YARN resources
(memory, cores)
-yqu,--yarnqueue <arg> Specify YARN queue.
-ys,--yarnslots <arg> Number of slots per TaskManager
-yst,--yarnstreaming Start Flink in streaming mode
-yt,--yarnship <arg> Ship files in the specified directory
(t for transfer)
-ytm,--yarntaskManagerMemory <arg> Memory per TaskManager Container with
optional unit (default: MB)
-yz,--yarnzookeeperNamespace <arg> Namespace to create the Zookeeper
sub-paths for high availability mode
-z,--zookeeperNamespace <arg> Namespace to create the Zookeeper
sub-paths for high availability mode
default mode可选项:
-m,--jobmanager <arg> Address of the JobManager (master) to which
to connect. Use this flag to connect to a
different JobManager than the one specified
in the configuration.
-z,--zookeeperNamespace <arg> Namespace to create the Zookeeper sub-paths
for high availability mode
5.2 提交Flink Job的三种方式
5.2.1 default mode-Yarn Session
5.2.1.1 概述
对应上面图例的右上。
此方式需要首先在Yarn中初始化一个持续运行的Flink Session集群(就是一个Yarn Application),并得到一个application_id,此时总的Container资源就确定了,也就是说所有后续提交到该Session集群的Job共享JM和TM。Client Develoyer就可通过命令行、RestAPI、WebUI等方式使用该id进行后续所有job提交运行(上传所需依赖的Dependencies jar包、生成JobGraph,然后提交到JM),不再需要每次都与Yarn交互了。
而且此模式下JM的生命周期不受提交的Job影响,会长期运行。
FlinkSession模式支持Native模式部署,即TM可动态申请。
Yarn-Session方式又包括两种方式:
-
普通模式,类似Spark中的Yarn-Client模式
如果使用Yarn Session Cluster模式,则启动后集群的运行依赖于本地Yarn Session本地启动进程,一旦该进程关闭则整个Session集群也会终止。改模式启动后,可在Yarn上看到该Flink Session生成的Application,并可点击对应URL进入Flink Web UI。
-
Detached-分离模式,类似Spark中的Yarn-Cluster模式
指定参数-d
或--detached
改为依附模式,即将Flink Session集群运行交给Yarn管理,不再依赖本地启动进程。这种模式不能使用flink命令停止yarn-session,需要使用
yarn application -kill <appId>
来停止该Flink Session集群。
5.2.1.2 Detached 模式例子
- 在Yarn上启动detached模式的常驻Flink集群,记录application_id。
启动一个2个TaskManager的Flink集群,为每个TaskManager的Container分配1GB内存,为JobManager分配1GB内存。$FLINK_HOME/bin/yarn-session.sh -n 2 -tm 1024 -jm 1024 -d
- detach到该Flink Session集群
$FLINK_HOME/bin/yarn-session.sh -id application_id
- 提交Job到该Flink Session集群执行
$FLINK_HOME/bin/flink run ./examples/streaming/WordCount.jar --input hdfs:///..../LICENSE-2.0.txt --output hdfs:///.../wordcount-result.txt
- 通过Flink集群WebUI查看Job
- 可通过WebUI或stop/cancel停止Job
5.2.1.3 小结
- 优点
- 资源固定
- 资源共享,利用率高
- 缺点
- 资源隔离较差
集群资源固定,如果前面的Job将资源占满,那么后续的Job可能会因为无足够资源只能等待。线上环境一般不用该模式。 - 不易扩展,计算资源伸缩性较差
- 资源隔离较差
5.2.2 yarn-cluster Per-Job mode
5.2.2.1 概述
对应上面图例的右下。
每个Job一个Yarn-Session Cluster,每次都单独申请资源,资源数量根据客户端提交Job时指定。客户端依然要负责生成和提交JobGraph和上传依赖jar。
此模式下JM的声明周期和Job相同。
5.2.2.2 例子
该模式需要使用$FLINK_HOME/bin/flink
,可以使用$FLINK_HOME/bin/yarn-session.sh
的参数,只不过参数名前加了y
或yarn
前缀。
此模式Job资源受Yarn分配队列的总资源限制。我们在线上生成环境使用的该模式。
- 提交任务
yarn-cluster模式,设置job并行为4,JobManager内存1GB,每个TaskManager内存4GB$FLINK_HOME/bin/flink run -m yarn-cluster -p 4 -yjm 1024m -ytm 4096m ./examples/batch/WordCount.jar
- 该模式每提交一个Job就有一个Yarn-Session集群,也对应了一个application_id
5.2.2.2 小结
优点:
- 资源隔离程度最高
- 资源申请数由客户端决定
缺点: - 资源利用率不高,需要用户仔细评估
5.2.3 Application Mode
5.2.3.1 Session和Per-Job问题
- 每次都需要上传用户Jar
- 每次都需要在用户客户端生成JobGraph
- 任务多时客户端压力大,因为每个任务是阻塞时提交,后续Job需要排队
5.2.3.2 概述
Flink 1.11中加入的新模式,公共Jar包提前放置到HDFS,然后Client将运行作业需要的依赖都通过Yarn Local Resource
传递到JM。
最重要的一点是 JobGraph
的生成以及Job的提交不再会在Client执行,而是转移到 JM 执行(也就是说Application的main()
方法从Client转到JM执行),客户端不需要上传Jar了而只需要负责Job提交和管理,这样网络下载上传的负载也会分散到集群中,不再有Client 单点瓶颈的问题。
注意,此模式下每个Application对应一个JM但,可以包含多个Job。
5.2.3.3 例子
可通过-Dyarn.provided.lib.dirs
指定依赖的包路径,就不用上传了。如果不指定会每次都上传依赖包。当然,这样提交后还是需要上传用户Jar,如下例的WordCount.jar
$FLINK_HOME/bin/flink run-application -t yarn-application \
-Djobmanager.memory.process.size=1024m \
-Dtaskmanager.memory.process.size=2048m \
-Dyarn.provided.lib.dirs="hdfs://xxx/flink" \
./WordCount.jar
当然,也可以把用户Jar也指定为HDFS上的Jar:
$FLINK_HOME/bin/flink run-application -t yarn-application \
-Djobmanager.memory.process.size=1024m \
-Dtaskmanager.memory.process.size=2048m \
-Dyarn.provided.lib.dirs="hdfs://xxx/flink" \
hdfs://xxx/flink-user/WordCount.jar
5.2.3.4 小结
优点:
- 降低带宽和客户端负载
- Application之间资源隔离
- Application内资源共享
缺点: - 生产案例较少
- 仅支持Yarn、K8S
5.3 Yarn容错配置
详情请参考Flink学习1-基础概念-HA
Flink On Yarn时需要依赖Yarn来实现高可用,Yarn会对失败挂掉的JobManager(AM)重启,最大重试次数的配置是yarn-site.xml
的yarn.resourcemanager.am.max-attempts
。
Flink的yarn-client有一些配置可以控制在container失败的情况下的行为,也可通过$FLINK_HOME/conf/flink-conf.yaml
或启动yarn-session.sh
时以-D
参数指定:
-
yarn.application-attempts
ApplicationMaster(运行着JobManager)及其TaskManager Container的最大失败重试次数。默认值为1,此时AM挂掉就直接导致整个flink yarn session失败了。所以一般需要设为较高的值,使得可在失败时可多次尝试重启AM。如果超过该阈值,不会再重启AM,该yarn session上提交的任务也会全部停止。
比如设为5时,代表初始化一次、最大重试4次。
注意该值不能超过yarn中
yarn.resourcemanager.am.max-attempts
配置的最大重启次数。
5.4 Job优先级
可通过$FLINK_HOME/conf/flink-conf.yaml
或启动yarn-session.sh
时以-D
参数指定:
-
yarn.application.priority
设为非负数时,指定Flink提交到Yarn上的Application的优先级,仅当Yarn开启了优先级调度时生效。更大的整数代表更高的优先级。如果设为负数或默认值-1,则不会设置yarn优先级,而是使用默认的集群优先级。
5.5 yarn session失败调试
5.5.1 日志文件
基于Yarn的日志聚合功能,在yarn-site.xml
配置yarn.log-aggregation-enable
为true,然后就能使用以下命令查看日志:
bin/yarn logs -applicationId <application_id>
5.5.2 yarn client 控制台或WebUI
- yarn client会在错误发生在运行期(比如某个TaskManager在工作一段时间后挂掉)时也会打印错误信息到控制台。
- Yarn WebUI也可看到错误日志
5.6 yarn-job停止
5.6.1 界面方式
进入flink job监控界面,点击进入要停止的Job
然后点击右上角的Cancel Job
5.6.2 yarn命令
- 查看任务状态
yarn application -status application_id
- kill任务
yarn application -kill application_id
5.7 从Checkpoint/Savepoint恢复
5.7.1 从Checkpoint恢复
可参考:
Checkpoint与Savepoint相比,有一些不同:
- Checkpoint使用 StateBackend 特定的数据格式,可以增量方式存储。
- Checkpoint不支持 Flink 的特定功能,比如扩缩容。
命令格式如下:
$ bin/flink run -s :checkpointMetaDataPath [:runArgs]
从Checkpoint恢复步骤实例:
- 先在flink监控界面看最近成功的那次checkpoint路径:
- Cancel要恢复的Flink任务
注意:必须先在代码或flink-conf.yaml
中配置checkpoint在Cancel后依然保留,否则checkpoint会在Cancel后删除!
val env = StreamExecutionEnvironment.getExecutionEnvironment
// checkpoint every 5 minute
.enableCheckpointing(5 * 60 * 1000)
val checkpointConfig = env.getCheckpointConfig
checkpointConfig.setMinPauseBetweenCheckpoints(2 * 60 * 1000)
checkpointConfig.setCheckpointTimeout(3 * 60 * 1000)
// cancel后仍然保留checkpoint
checkpointConfig.enableExternalizedCheckpoints(ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION)
- 启动恢复任务
注意要找到chk-xxx
目录的下一级_metadata
目录来恢复任务:$ bin/flink run -m yarn-cluster -ynm kafka-to-hdfs -yjm 2048m -ytm 8192m -p 40 -s hdfs:/tmp/flink/flink-checkpoints/v78e8c6f8b885cab29c11976bd5c8hj8/chk-111/_metadata ./user_jars/kafka2hdfs-1.0-SNAPSHOT.jar --groupid Kafka2Hive &
5.7.2 从Savepoint恢复
可参考:
5.7.2.1 Trigger a Savepoint
命令格式:
./bin/flink savepoint <jobId> [savepointDirectory]
- savepointDirectory可选(该路径必须是JobManager可访问),如果flink-conf.yaml中配置了
state.savepoints.dir
则可以不填,如果没配也没填否则会导致savepoint失败。 - 命令执行后会返回savepoint的路径信息,该信息被用来恢复Flink任务或杀死savepoint。
5.7.2.2 Trigger a Savepoint with YARN
该命令是针对Yarn上的Flink程序生成Savepoint。
命令格式:
./bin/flink savepoint <jobId> [savepointDirectory] -yid <yarnAppId>
- savepointDirectory可选(该路径必须是JobManager可访问),如果flink-conf.yaml中配置了
state.savepoints.dir
则可以不填,如果没配也没填否则会导致savepoint失败。 - yid为Flink程序在Yarn上运行的application id
- 命令执行后会返回savepoint的路径信息,该信息被用来恢复Flink任务或杀死savepoint。
5.7.2.3 Stop
该命令用来优雅停止一个Flink Streaming Job,并同时生成savepoint。
命令格式:
./bin/flink stop [-p targetDirectory] [-d] <jobID>
stop
命令是停止正在运行的Flink Streaming Job的一种更为优雅的方法,因为stop
信号从source流向sink。
- 具体来说,当我们发出
stop
命令时,所有source
会收到请求,随后发送最后一次checkpoint barrier
给下游触发一次savepoint。 - savepoint成功执行后,触发
SourceFunction.cancel()
结束Source。 - 如果加入了
-d
选项,则new Watermark(Long.MAX_VALUE)
会在最后一个checkpoint barrier之前被发送到。这会导致所有已注册的event-time timer被触发,随后flush所有等待特殊watermark的state,比如Window计算。 - 该job会继续运行一段时间,直到所有Source正确关闭,处理完所有传输中数据。所有称为
优雅关闭
.
5.7.2.4 Cancel with a savepoint (deprecated)
原子性的触发Savepoint并Cancel一个job:
./bin/flink cancel -s [savepointDirectory] <jobID>
- savepointDirectory可选(该路径必须是JobManager可访问),如果flink-conf.yaml中配置了
state.savepoints.dir
则可以不填,如果没配也没填否则会导致savepoint失败。 - Job只会在savepoint成功后Cancel
- 注意:本方法已经被标记为
deprecated
,使用stop
替代
5.7.2.5 Restore a savepoint
从Savepoint中恢复Flink job:
./bin/flink run -s <savepointPath> ...
-
run
提交job时带有-s <savepointPath>
即可从该路径对应的savepoint中恢复,这里的路径就是我们之前用savepoint
或stop
命令停止后得到的。 -
默认会恢复所有savepoint state,如果想跳过一些不适用于新job的savepoint state可设置
allowNonRestoredState
。比如新Job从代码中移除了一个算子,就可以这么做。
./bin/flink run -s <savepointPath> -n ...
5.7.2.6 Dispose a savepoint
丢弃指定路径的savepoint:
./bin/flink savepoint -d <savepointPath>
如果使用了自定义state,比如自定义reduce、RocksDB等,需要同时指定该job的jar包路径,才能通过用户代码的ClassLoader来丢弃该savepoint,否则会报错ClassNotFoundException
:
./bin/flink savepoint -d <savepointPath> -j <jarFile>
也可以手动从文件系统删除savepoint目录,不会影响别的savepoint/checkpoint。
5.8 Flink 启动配置
可参考
5.8.1 flink-conf.yaml
可以在该文件中设置所有支持的Flink Option,格式如:
env.java.opts: -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+AlwaysPreTouch -server -XX:+HeapDumpOnOutOfMemoryError
jobmanager.rpc.address: localhost
jobmanager.rpc.port: 6123
5.8.2 -yD
可以在启动flink on yarn时通过-yD
参数指定,比如:
./flink-1.2.0/bin/flink run -m yarn-cluster -yn 4 -yjm 2048 -ytm 8086 -c beam.count.OpsCount -yqu data-default \
-yD taskmanager.heap.size=4096 -yD yarn.heap-cutoff-ratio=0.6 -yD taskmanager.debug.memory.startLogThread=true -yD taskmanager.debug.memory.logIntervalMs=600000 \
-yz toratest -yst -yd ./xxx.jar --parallelism=4
-yD env.java.opts="-XX:NewRatio=2"
此时用jmap -heap
看一个container内存情况如下:
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 2359296000 (2250.0MB)
NewSize = 786432000 (750.0MB)
MaxNewSize = 786432000 (750.0MB)
OldSize = 1572864000 (1500.0MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 476053504 (454.0MB)
used = 224818576 (214.40370178222656MB)
free = 251234928 (239.59629821777344MB)
47.225484974058716% used
From Space:
capacity = 101187584 (96.5MB)
used = 85147536 (81.20301818847656MB)
free = 16040048 (15.296981811523438MB)
84.14820537665965% used
To Space:
capacity = 155189248 (148.0MB)
used = 0 (0.0MB)
free = 155189248 (148.0MB)
0.0% used
PS Old Generation
capacity = 1572864000 (1500.0MB)
used = 922110224 (879.3928375244141MB)
free = 650753776 (620.6071624755859MB)
58.62618916829427% used
22206 interned Strings occupying 2255248 bytes.
5.8.3 JVM参数设置
可参考:
5.8.3.1 Flink Java 配置项
Key | Default | Type | Description |
---|---|---|---|
env.hadoop.conf.dir | (none) | String | Path to hadoop configuration directory. It is required to read HDFS and/or YARN configuration. You can also set it via environment variable. |
env.java.opts | (none) | String | 用于启动所有Flink进程的JVM的Java配置 |
env.java.opts.historyserver | (none) | String | JVM HistoryServer java配置项 |
env.java.opts.jobmanager | (none) | String | JVM JobManager java配置项 |
env.java.opts.taskmanager | (none) | String | JVM TaskManager java配置项 |
env.log.dir | (none) | String | Defines the directory where the Flink logs are saved. It has to be an absolute path. (Defaults to the log directory under Flink’s home) |
env.log.max | 5 | Integer | The maximum number of old log files to keep. |
env.ssh.opts | (none) | String | Additional command line options passed to SSH clients when starting or stopping JobManager, TaskManager, and Zookeeper services (start-cluster.sh, stop-cluster.sh, start-zookeeper-quorum.sh, stop-zookeeper-quorum.sh). |
env.yarn.conf.dir | (none) | String | Path to yarn configuration directory. It is required to run flink on YARN. You can also set it via environment variable. |
5.8.3.2 JVM常用配置
详细配置可参考
堆设置
-Xms :初始堆大小
-Xmx :最大堆大小
-Xmn:设置年轻代大小
-XX:NewSize=n :设置年轻代大小
-XX:NewRatio=n: 设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
-XX:SurvivorRatio=n :年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
-XX:MaxPermSize=n :设置持久代大小
收集器设置
-XX:+UseSerialGC :设置串行收集器
-XX:+UseParallelGC :设置并行收集器
-XX:+UseParalledlOldGC :设置并行年老代收集器
-XX:+UseConcMarkSweepGC :设置并发收集器
垃圾回收统计信息
-XX:+PrintHeapAtGC GC的heap详情
-XX:+PrintGCDetails GC详情
-XX:+PrintGCTimeStamps 打印GC时间信息
-XX:+PrintTenuringDistribution 打印年龄信息等
-XX:+HandlePromotionFailure 老年代分配担保(true or false)
并行收集器设置
-XX:ParallelGCThreads=n :设置并行收集器收集时使用的CPU数。并行收集线程数。
-XX:MaxGCPauseMillis=n :设置并行收集最大暂停时间
-XX:GCTimeRatio=n :设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
并发收集器设置
-XX:+CMSIncrementalMode :设置为增量模式。适用于单CPU情况。
-XX:ParallelGCThreads=n :设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数
5.9 Flink On Yarn小结
优点
- 直接对接主流Hadoop 2.4+版本
- Yarn是主流调度技术,可支持大多大数据栈,如MR、Spark等,统一资源管理
- 由Yarn负责资源管理,用户只需专注Flink代码开发
- 支持Native模式部署,动态申请TM资源,提高资源利用率
- 可利用Yarn Failover机制实现JM、TM容错
缺点 - Yarn黑盒,出现问题不好排查
- Yarn对内存隔离做的较好,但对其他资源如CPU、网络隔离做的较差
6 Flink On Kubernetes
7 监控
7.1 概述
在flink系统中,可以通过REST API、Flink WebUI等方式查看Flink系统指标,还可以通过代码方式自定义指标注册到Flink。
此外还能配置Reporter来将Flink指标暴露给第三方监控工具,比如Prometheus等。
7.2 Prometheus配置
- 需要先将
flink-metrics-prometheus_2.11-1.9.0.jar
拷贝到$FLINK_HOME/lib
- 修改
flink-conf.yaml
vim $FLINK_HOME/conf/flink-conf.yaml # 加入以下内容 metrics.reporter.prom.class: org.apache.flink.metrics.prometheus.PrometheusReporter # 每个task container就要用一个exporter实例占用一个端口 # ,所以需要用端口范围 metrics.reporter.prom.port: 9250-9350
6.3 背压Back Pressure
可参考:
8 调优
81 内存调优
8.1.1 内存调优指南
8.1.2 Flink JobManager内存调优
参考:
总结
本篇文章主要讲了下Flink的安装和示例程序的提交,希望大家有所收获。
下一章我们学习下Flink的API,看看Flink作者是怎么抽象API的:
Flink系列3-API介绍