一、Apache Flink 背景简介
Apache Flink项目是大数据计算领域冉冉升起的一颗新星,其中大数据领域的处理引擎的发展经历了几个重要的历程:由一代的MapReduce的矢量编程模式从Map端到Reduce端带领当着当时的大小企业开始了最为原始的大数据集的处理方式;二代基于DAG编程模式的Tez和基于纯流式模型的Strom,正式开启了由批式处理转为流式处理的大门;发展到后来的基于RDD(弹性分布式数据集)的Spark,在当时可以说做数据处理业务不懂Spark就相当于是不是真正意义上的工程师;最后登场的就是我们最后的主角
Apache Flink:最早于2008年在德国柏林理工大学为开放性研究实验室的一个项目,2014年4月份以孵化项目的形式进入Apache软件基金会,并在次年一月份称为Apache的顶级项目。截止到目前为止Flink社区中贡献代码人数已经超过500人,并在不断普及的过程中成为开源界最为先进的流式处理引擎项目。在国内使用Apache Flink(以下所有Apache Flink简称为‘Flink’)最为热烈的公司就是阿里巴巴。
2018年12月20日,由阿里巴巴承办的Flink Forword China 峰会在北京国家会议中心召开,来自阿里、华为、腾讯、美团、字节跳动等一系列国内著名互联网公司参与并分享了使用基于Flink处理引擎的业务应用以及宝贵的经验,同时最为重要的是阿里巴巴在会议上宣布了开源阿里巴巴内部版本的‘Flink项目’Blink处理引擎;由此可见未来大数据的发展趋势以及越来越多公司业务对于实时性的要求,Flink在不久以后会成为处理引擎的标准。
二、Apache Flink 特点
- 分布式:Flink程序可以运行在多台机器上
- 高性能:Flink是目前所有大数据处理引擎中唯一一个在流处理之上构建批处理,支持高吞吐、低延迟
- 高可用:由于Flink服务十分稳定,如果支持超大规模数据集的批处理和流处理计算模型,导致Flink必须可以保证在某个节点宕机后的业务处理可以继续正常运行,故支持HA(高可用集群)
- 准确:Flink处理引擎是目前市场上为数不多支持Exactly-once(精准一次处理)语义级别
- 流式优先计算原则:Flink优先保证连续处理流式数据
- 容错计算:Flink提供了有状态的计算,可以记录数据的处理状态,当数据处理失败的情况下,能够无缝的从失败中恢复,从而实现第四条特点保证Flink的Exactly-once语义级别的处理
- 集群可伸缩性:Flink中的一个集群可以支持上千个节点
三、Apache Flink 编程架构分析
以上图面截取自Apache Flink 官方社区:https://ci.apache.org/projects/flink/flink-docs-release-1.10/internals/components.html
下面我们进行逐层分析FlinkAPI架构:
- Deploy(调度、部署层):Flink支持本地部署模式、集群部署模式、云服务器部署模式,其中本地部署模式就是利用到JVM;集群部署模式支持分布式、伪分布式模式支持Standalone模式或者使用Hadoop中的YARN集群部署模式,如果部署HA模式,需要三方分布式协调服务例如ZOOKEEPER等;云服务部署就是常用的GCE、EC2等。
- Core(核心API层):该层就是Flink最底层的、最为核心的但是不适合大多数编程人员使用的层次,这一层主要架构起在该层之上的DataSet和DataStream编程API,可以理解为该层是Flink架构中最为重要的一层,撑起了高阶API的使用。
- API&Libraries(API语言层):该层级是分为两种DataSet和DataStream,其中DataSetAPI是构建了Flink的批处理API;DataStream是构建了Flink的流处理API;该层级是编程人员在处理开发任务中最为常用的层级,稍后在代码层面会做更多的说明。
- 另外在中间API层之上又构建出来了更为高阶的API,也是自从Flink1.7版本之后开源的Flink SQL和Flink Table,这两种编程模型专门将对数据转换过程变为我们熟悉的SQL语句,通过SQL开发极大的增加了开发人员的编程效率并同时提高业务水平,之后也会在后面的章节中专门为大家讲解下SQL和Table的开发案例。
四、Apache Flink集群部署模式
Flink部署基于Hadoop的Standlone集群模式按键HA必须依赖于Zookeeper来实现,在Zookeeper的环境下一个Flink集群会有多个或者的JobManager,其中一个是Master,其余的JobManager为Slave,当Master宕机或者出现故障的时候,其余的Slave中的某个JobManager节点会成为Master,从而实现集群的HA。
下载地址:https://flink.apache.org/downloads.html
本版本是Flink的最新版本:Apache Flink 1.10.1
虚拟机:Centos 7
Hadoop 环境:hadoop-2.9.2
Zookeeper环境:zookeeper-3.4.6
JDK环境:java1.8+
Scala环境:2.11
(一) 安装JDK
[root@CentOSX ~] rpm -ivh jdk-8u191-linux-x64.rpm
[root@CentOSX ~] vi /etc/profile
JAVA_HOME=/home/java/ jdk-8u191-linux-x64
PATH=/home/java/ jdk-8u191-linux-x64/bin
CLASSPATH=.
export JAVA_HOME
export PATH
export CLASSPATH
[root@CentOSX ~] souce /etc/profile
[root@CentOSX ~] java -version
java version “1.8.0_191”
Java™ SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot™ 64-Bit Server VM (build 25.191-b12, mixed mode)
(二) 搭建Zookeeper集群
[root@CentOSX ~]# tar -zxf zookeeper-3.4.6.tar.gz -C /home/zookeeper/
[root@CentOSX ~]# mkdir /root/zkdata
[root@CentOSA ~]# echo 1 >> /root/zkdata/myid
[root@CentOSB ~]# echo 2 >> /root/zkdata/myid
[root@CentOSC ~]# echo 3 >> /root/zkdata/myid
[root@CentOSX ~]# vi /home/zookeeper/zookeeper-3.4.6/conf/zoo.cfg
tickTime=2000
dataDir=/root/zkdata
clientPort=2181
initLimit=5
syncLimit=2
server.1=CentOSA:2887:3887
server.2=CentOSB:2887:3887
server.3=CentOSC:2887:3887
[root@CentOSX ~]# /home/zookeeper/zookeeper-3.4.6/bin/zkServer.sh start zoo.cfg
[root@CentOSX ~]# /home/zookeeper/zookeeper-3.4.6/bin/zkServer.sh status zoo.cfg
JMX enabled by default
Using config: /home/zookeeper/zookeeper-3.4.6/bin/…/conf/zoo.cfg
Mode:2 follower|1 leader
(三) 搭建HDFS-HA
[root@CentOSX ~]# tar -zxf hadoop-2.9.2.tar.gz -C /home/hadoop/
[root@CentOSX ~]# vi /etc/profile
HADOOP_HOME=/home/hadoop/hadoop-2.9.2/
JAVA_HOME=/home/java/ jdk-8u191-linux-x64
PATH=/home/java/ jdk-8u191-linux-x64/bin:/home/hadoop/hadoop-2.9.2/bin:/home/hadoop/hadoop-2.9.2/sbin
CLASSPATH=.
export JAVA_HOME
export PATH
export CLASSPATH
export HADOOP_HOME
export HADOOP_CLASSPATH=hadoop classpath
[root@CentOSX ~]# source /etc/profile
注意配置HADOOP_CLASSPATH ,因为Flink里面需要继承HDFS存储State
- 配置core-site.xml
<!--配置Namenode服务ID-->
<property>
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/hadoop-2.9.2/hadoop-${user.name}</value>
</property>
<property>
<name>fs.trash.interval</name>
<value>30</value>
</property>
<!--配置机架脚本-->
<property>
<name>net.topology.script.file.name</name>
<value>/home/hadoop/hadoop-2.9.2/etc/hadoop/rack.sh</value>
</property>
<!--配置ZK服务信息-->
<property>
<name>ha.zookeeper.quorum</name>
<value>CentOSA:2181,CentOSB:2181,CentOSC:2181</value>
</property>
<!--配置SSH秘钥位置-->
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/root/.ssh/id_rsa</value>
</property>
- 配置机架脚本
[root@CentOSX ~]# vi /home/hadoop/hadoop-2.9.2/etc/hadoop/rack.sh
while [ $# -gt 0 ] ; do
nodeArg=$1
exec</home/hadoop/hadoop-2.9.2/etc/hadoop/topology.data
result=""
while read line ; do
ar=( $line )
if [ "${ar[0]}" = "$nodeArg" ] ; then
result="${ar[1]}"
fi
done
shift
if [ -z "$result" ] ; then
echo -n "/default-rack"
else
echo -n "$result "
fi
done
[root@CentOSX ~]# chmod u+x /home/hadoop/hadoop-2.9.2/etc/hadoop/rack.sh
192.168.221.136 /rack01
192.168.221.137 /rack02
192.168.221.138 /rack03
- 配置hdfs-site.xml
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
<!--开启自动故障转移-->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!--解释core-site.xml内容-->
<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>CentOSA:9000</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>CentOSB:9000</value>
</property>
<!--配置日志服务器的信息-->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://CentOSA:8485;CentOSB:8485;CentOSC:8485/mycluster</value>
</property>
<!--实现故障转切换的实现类-->
<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
- 配置slaves
CentOSA
CentOSB
CentOSC
- 启动HDFS(集群初始化启动)
[root@CentOSX ~]# hadoop-daemon.sh start journalnode (等待10s钟)
[root@CentOSA ~]# hdfs namenode -format
[root@CentOSA ~]# hadoop-daemon.sh start namenode
[root@CentOSB ~]# hdfs namenode -bootstrapStandby
[root@CentOSB ~]# hadoop-daemon.sh start namenode
#注册Namenode信息到zookeeper中,只需要在CentOSA或者B上任意一台执行一下指令
[root@CentOSA|B ~]# hdfs zkfc -formatZK
[root@CentOSA ~]# hadoop-daemon.sh start zkfc
[root@CentOSB ~]# hadoop-daemon.sh start zkfc
[root@CentOSX ~]# hadoop-daemon.sh start datanode
(四) 搭建Flink集群
[root@CentOSX ~]# tar -zxvf flink-1.10.1-bin-scala_2.11.tgz -C /home/flink/
[root@CentOSX ~]# vi /home/flink/flink-1.10.1/conf/flink-conf.yaml
taskmanager.numberOfTaskSlots: 4
parallelism.default: 3
high-availability: zookeeper
high-availability.zookeeper.quorum: CentOSA:2181,CentOSB:2181,CentOSC:2181
high-availability.zookeeper.path.root: /flink
high-availability.cluster-id: /default_ns
high-availability.storageDir: hdfs:///flink/ha/
state.backend: rocksdb
state.checkpoints.dir: hdfs:///flink-checkpoints
state.savepoints.dir: hdfs:///flink-savepoints
state.backend.incremental: true
state.backend.rocksdb.ttl.compaction.filter.enabled: true
jobmanager.archive.fs.dir: hdfs:///completed-jobs/
historyserver.web.address: 0.0.0.0
historyserver.web.port: 8082
historyserver.archive.fs.dir: hdfs:///completed-jobs/
historyserver.archive.fs.refresh-interval: 10000
[root@CentOSX ~]# vi /home/flink/flink-1.10.1/conf/masters
CentOSA:8081
CentOSB:8081
CentOSC:8081
[root@CentOSX ~]# vi /home/flink/flink-1.10.1/conf/slaves
CentOSA
CentOSB
CentOSC
[root@CentOSA flink-1.10.1]# ./bin/start-cluster.sh
Starting HA cluster with 3 masters.
Starting standalonesession daemon on host CentOSA.
Starting standalonesession daemon on host CentOSB.
Starting standalonesession daemon on host CentOSC.
Starting taskexecutor daemon on host CentOSA.
Starting taskexecutor daemon on host CentOSB.
Starting taskexecutor daemon on host CentOSC.
- webUI
以上至此Flink-HA搭建完毕,下面会基于以上搭建的Flink-HA集群提交Job运行,让我们体验下Flink的带给我的快感
。
五、Apache Flink-HA 安装过程中出现的问题
java.lang.NoClassDefFoundError: org/apache/hadoop/yarn/exceptions/YarnException
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at org.apache.flink.client.cli.CliFrontend.loadCustomCommandLine(CliFrontend.java:1076)
at org.apache.flink.client.cli.CliFrontend.loadCustomCommandLines(CliFrontend.java:1030)
at org.apache.flink.client.cli.CliFrontend.main(CliFrontend.java:957)
Caused by: java.lang.ClassNotFoundException: org.apache.hadoop.yarn.exceptions.YarnException
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
… 5 more
该问题可以参考以下Flink官网的提示
https://ci.apache.org/projects/flink/flink-docs-release-1.10/ops/deployment/hadoop.html
将Hadoop中flink-shaded-hadoop-2-uber.jar引入到Flink的lib依赖中,并且需要配置Hadoop的环境变量
https://repo.maven.apache.org/maven2/org/apache/flink/flink-shaded-hadoop-2-uber/
最后可以启动下Flink中内置的word count程序进行测试啦。
启动命令:
flink run -m yarn-cluster /home/flink-1.10.1/examples/streaming/WordCount.jar
======================================== END =================================
下一节我们开始接触到Flink的编程模型,以及JobManager\TaskManager的数据结构,真正的体验到Flink带给我们的快感!
ps:有任何疑问欢迎留言!关注~