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-Configuration

配置项应写入$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(并行度)。

我们可以有多种方法设置并行度,优先级从高到低为:

  1. 算子级别
val text: DataStream[String] = env.socketTextStream(hostname, port, '\n')
text.flatMap { w => w.split("\\s") }.setParallelism(2)
  1. ExecutionEnvironment 级别
val bsEnv = StreamExecutionEnvironment.getExecutionEnvironment
    bsEnv.setParallelism(1)
  1. 提交时命令行指定
    将job并行度设为40
bin/flink run -m yarn-cluster ... -p 40 ...
  1. 配置文件(flink-conf.yaml)级别
    parallelism.default: 4

2.2.2 内存配置

参考:

3 Standalone模式Flink集群启动

可参考Standalone Cluster

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 cdc mysql 安装 flink安装需要什么条件_flink


可以从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

DataStream API Tutorial

构建过程如遇问题可参考Flink Maven archetype:generate

用Maven骨架构建Flink初始工程需要使用Maven 3.0.4+以及Java 8.x,然后有以下两种方式构建初始工程:

  • mvn archetype:generate方式
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界面:

flink cdc mysql 安装 flink安装需要什么条件_scala_02

点击这行job信息能看到job详情页:

flink cdc mysql 安装 flink安装需要什么条件_apache_03

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_DIRHADOOP_CONF_DIRHADOOP_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的三种方式

flink cdc mysql 安装 flink安装需要什么条件_apache_04

5.2.1 default mode-Yarn Session

5.2.1.1 概述

flink cdc mysql 安装 flink安装需要什么条件_flink cdc mysql 安装_05

对应上面图例的右上。

此方式需要首先在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 模式例子
  1. 在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
  1. detach到该Flink Session集群
$FLINK_HOME/bin/yarn-session.sh -id application_id
  1. 提交Job到该Flink Session集群执行
$FLINK_HOME/bin/flink run ./examples/streaming/WordCount.jar --input hdfs:///..../LICENSE-2.0.txt --output hdfs:///.../wordcount-result.txt
  1. 通过Flink集群WebUI查看Job
  2. 可通过WebUI或stop/cancel停止Job
5.2.1.3 小结
  • 优点
  • 资源固定
  • 资源共享,利用率高
  • 缺点
  • 资源隔离较差
    集群资源固定,如果前面的Job将资源占满,那么后续的Job可能会因为无足够资源只能等待。线上环境一般不用该模式。
  • 不易扩展,计算资源伸缩性较差

5.2.2 yarn-cluster Per-Job mode

5.2.2.1 概述

flink cdc mysql 安装 flink安装需要什么条件_apache_06

对应上面图例的右下。

每个Job一个Yarn-Session Cluster,每次都单独申请资源,资源数量根据客户端提交Job时指定。客户端依然要负责生成和提交JobGraph和上传依赖jar。

此模式下JM的声明周期和Job相同。

5.2.2.2 例子

该模式需要使用$FLINK_HOME/bin/flink,可以使用$FLINK_HOME/bin/yarn-session.sh的参数,只不过参数名前加了yyarn前缀。

此模式Job资源受Yarn分配队列的总资源限制。我们在线上生成环境使用的该模式。

  1. 提交任务
    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
  1. 该模式每提交一个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.xmlyarn.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

flink cdc mysql 安装 flink安装需要什么条件_flink_07


然后点击右上角的Cancel Job

flink cdc mysql 安装 flink安装需要什么条件_scala_08

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恢复步骤实例:

  1. 先在flink监控界面看最近成功的那次checkpoint路径:
  2. 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)
  1. 启动恢复任务
    注意要找到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。

  1. 具体来说,当我们发出stop命令时,所有source会收到请求,随后发送最后一次checkpoint barrier给下游触发一次savepoint。
  2. savepoint成功执行后,触发SourceFunction.cancel()结束Source。
  3. 如果加入了-d选项,则new Watermark(Long.MAX_VALUE)会在最后一个checkpoint barrier之前被发送到。这会导致所有已注册的event-time timer被触发,随后flush所有等待特殊watermark的state,比如Window计算。
  4. 该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中恢复,这里的路径就是我们之前用savepointstop命令停止后得到的。
  • 默认会恢复所有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 监控

可参考flink-metrics-monitor

7.1 概述

在flink系统中,可以通过REST API、Flink WebUI等方式查看Flink系统指标,还可以通过代码方式自定义指标注册到Flink。

此外还能配置Reporter来将Flink指标暴露给第三方监控工具,比如Prometheus等。

7.2 Prometheus配置

  1. 需要先将flink-metrics-prometheus_2.11-1.9.0.jar拷贝到$FLINK_HOME/lib
  2. 修改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介绍

0xFF 参考文档