Apache 流框架 Flink,Spark Streaming,Storm对比分析(2)

此文已由做者岳猛受权网易云社区发布。
html

欢迎访问网易云社区,了解更多网易技术产品运营经验。java

2.Spark Streaming架构及特性分析


2.1 基本架构

基因而spark core的spark streaming架构。算法

Spark Streaming是将流式计算分解成一系列短小的批处理做业。这里的批处理引擎是Spark,也就是把Spark Streaming的输入数据按照batch size(如1秒)分红一段一段的数据(Discretized Stream),每一段数据都转换成Spark中的RDD(Resilient Distributed Dataset),而后将Spark Streaming中对DStream的Transformation操做变为针对Spark中对RDD的Transformation操做,将RDD经 过操做变成中间结果保存在内存中。整个流式计算根据业务的需求能够对中间的结果进行叠加,或者存储到外部设备。数据库

简而言之,Spark Streaming把实时输入数据流以时间片Δt (如1秒)为单位切分红块,Spark Streaming会把每块数据做为一个RDD,并使用RDD操做处理每一小块数据。每一个块都会生成一个Spark Job处理,而后分批次提交job到集群中去运行,运行每一个job的过程和真正的spark 任务没有任何区别。apache

JobScheduler

负责job的调度编程

JobScheduler是SparkStreaming 全部Job调度的中心, JobScheduler的启动会致使ReceiverTracker和JobGenerator的启动。ReceiverTracker的启动致使运行在Executor端的Receiver启动而且接收数据,ReceiverTracker会记录Receiver接收到的数据meta信息。JobGenerator的启动致使每隔BatchDuration,就调用DStreamGraph生成RDD Graph,并生成Job。JobScheduler中的线程池来提交封装的JobSet对象(时间值,Job,数据源的meta)。Job中封装了业务逻辑,致使最后一个RDD的action被触发,被DAGScheduler真正调度在Spark集群上执行该Job。安全

JobGenerator

负责Job的生成服务器

经过定时器每隔一段时间根据Dstream的依赖关系生一个一个DAG图。网络

ReceiverTracker

负责数据的接收,管理和分配架构

ReceiverTracker在启动Receiver的时候他有ReceiverSupervisor,其实现是ReceiverSupervisorImpl, ReceiverSupervisor自己启动的时候会启动Receiver,Receiver不断的接收数据,经过BlockGenerator将数据转换成Block。定时器会不断的把Block数据经过BlockManager或者WAL进行存储,数据存储以后ReceiverSupervisorImpl会把存储后的数据的元数据Metadate汇报给ReceiverTracker,实际上是汇报给ReceiverTracker中的RPC实体ReceiverTrackerEndpoint,主要。


2.2 基于Yarn层面的架构分析

上图为spark on yarn 的cluster模式,Spark on Yarn启动后,由Spark AppMaster中的driver(在AM的里面会启动driver,主要是StreamingContext对象)把Receiver做为一个Task提交给某一个Spark Executor;Receive启动后输入数据,生成数据块,而后通知Spark AppMaster;Spark AppMaster会根据数据块生成相应的Job,并把Job的Task提交给空闲Spark Executor 执行。图中蓝色的粗箭头显示被处理的数据流,输入数据流能够是磁盘、网络和HDFS等,输出能够是HDFS,数据库等。对比Flink和spark streaming的cluster模式能够发现,都是AM里面的组件(Flink是JM,spark streaming是Driver)承载了task的分配和调度,其余container承载了任务的执行(Flink是TM,spark streaming是Executor),不一样的是spark streaming每一个批次都要与driver进行通讯来进行从新调度,这样延迟性远低于Flink。

具体实现

图2.1 Spark Streaming程序转换为DStream Graph

图2.2 DStream Graph转换为RDD的Graph


Spark Core处理的每一步都是基于RDD的,RDD之间有依赖关系。下图中的RDD的DAG显示的是有3个Action,会触发3个job,RDD自下向上依 赖,RDD产生job就会具体的执行。从DSteam Graph中能够看到,DStream的逻辑与RDD基本一致,它就是在RDD的基础上加上了时间的依赖。RDD的DAG又能够叫空间维度,也就是说整个 Spark Streaming多了一个时间维度,也能够成为时空维度,使用Spark Streaming编写的程序与编写Spark程序很是类似,在Spark程序中,主要经过操做RDD(Resilient Distributed Datasets弹性分布式数据集)提供的接口,如map、reduce、filter等,实现数据的批处理。而在Spark Streaming中,则经过操做DStream(表示数据流的RDD序列)提供的接口,这些接口和RDD提供的接口相似。Spark Streaming把程序中对DStream的操做转换为DStream Graph,图2.1中,对于每一个时间片,DStream Graph都会产生一个RDD Graph;针对每一个输出操做(如print、foreach等),Spark Streaming都会建立一个Spark action;对于每一个Spark action,Spark Streaming都会产生一个相应的Spark job,并交给JobScheduler。JobScheduler中维护着一个Jobs队列, Spark job存储在这个队列中,JobScheduler把Spark job提交给Spark Scheduler,Spark Scheduler负责调度Task到相应的Spark Executor上执行,最后造成spark的job。

图2.3时间维度生成RDD的DAG

Y轴就是对RDD的操做,RDD的依赖关系构成了整个job的逻辑,而X轴就是时间。随着时间的流逝,固定的时间间隔(Batch Interval)就会生成一个job实例,进而在集群中运行。


代码实现

基于spark 1.5的spark streaming源代码解读,基本架构是没怎么变化的。

2.3 组件栈

支持从多种数据源获取数据,包括Kafk、Flume、Twitter、ZeroMQ、Kinesis 以及TCP sockets,从数据源获取数据以后,可使用诸如map、reduce、join和window等高级函数进行复杂算法的处理。最后还能够将处理结果 存储到文件系统,数据库和现场仪表盘。在“One Stack rule them all”的基础上,还可使用Spark的其余子框架,如集群学习、图计算等,对流数据进行处理。

2.4 特性分析

吞吐量与延迟性

Spark目前在EC2上已可以线性扩展到100个节点(每一个节点4Core),能够以数秒的延迟处理6GB/s的数据量(60M records/s),其吞吐量也比流行的Storm高2~5倍,图4是Berkeley利用WordCount和Grep两个用例所作的测试,在 Grep这个测试中,Spark Streaming中的每一个节点的吞吐量是670k records/s,而Storm是115k records/s。

Spark Streaming将流式计算分解成多个Spark Job,对于每一段数据的处理都会通过Spark DAG图分解,以及Spark的任务集的调度过程,其最小的Batch Size的选取在0.5~2秒钟之间(Storm目前最小的延迟是100ms左右),因此Spark Streaming可以知足除对实时性要求很是高(如高频实时交易)以外的全部流式准实时计算场景。

exactly-once 语义

更加稳定的exactly-once语义支持。

反压能力的支持

Spark Streaming 从v1.5开始引入反压机制(back-pressure),经过动态控制数据接收速率来适配集群数据处理能力.

Sparkstreaming如何反压?

简单来讲,反压机制须要调节系统接受数据速率或处理数据速率,然而系统处理数据的速率是无法简单的调节。所以,只能估计当前系统处理数据的速率,调节系统接受数据的速率来与之相匹配。

Flink如何反压?

严格来讲,Flink无需进行反压,由于系统接收数据的速率和处理数据的速率是天然匹配的。系统接收数据的前提是接收数据的Task必须有空闲可用的Buffer,该数据被继续处理的前提是下游Task也有空闲可用的Buffer。所以,不存在系统接受了过多的数据,致使超过了系统处理的能力。

由此看出,Spark的micro-batch模型致使了它须要单独引入反压机制。

反压与高负载

反压一般产生于这样的场景:短时负载高峰致使系统接收数据的速率远高于它处理数据的速率。

可是,系统可以承受多高的负载是系统数据处理能力决定的,反压机制并非提升系统处理数据的能力,而是系统所面临负载高于承受能力时如何调节系统接收数据的速率。

容错

Driver和executor采用预写日志(WAL)方式去保存状态,同时结合RDD自己的血统的容错机制。

API 和 类库

Spark 2.0中引入告终构化数据流,统一了SQL和Streaming的API,采用DataFrame做为统一入口,可以像编写普通Batch程序或者直接像操做SQL同样操做Streaming,易于编程。

普遍集成

除了能够读取HDFS, Flume, Kafka, Twitter andZeroMQ数据源之外,咱们本身也能够定义数据源,支持运行在Yarn,Standalone及EC2上,可以经过Zookeeper,HDFS保证高可用性,处理结果能够直接写到HDFS

部署性

依赖java环境,只要应用可以加载到spark相关的jar包便可。

3.Storm架构及特性分析

3.1 基本架构


Storm集群采用主从架构方式,主节点是Nimbus,从节点是Supervisor,有关调度相关的信息存储到ZooKeeper集群中。架构以下:

Nimbus

Storm集群的Master节点,负责分发用户代码,指派给具体的Supervisor节点上的Worker节点,去运行Topology对应的组件(Spout/Bolt)的Task。

Supervisor

Storm集群的从节点,负责管理运行在Supervisor节点上的每个Worker进程的启动和终止。经过Storm的配置文件中的supervisor.slots.ports配置项,能够指定在一个Supervisor上最大容许多少个Slot,每一个Slot经过端口号来惟一标识,一个端口号对应一个Worker进程(若是该Worker进程被启动)。

ZooKeeper

用来协调Nimbus和Supervisor,若是Supervisor因故障出现问题而没法运行Topology,Nimbus会第一时间感知到,并从新分配Topology到其它可用的Supervisor上运行。

运行架构

运行流程

1)户端提交拓扑到nimbus。

2) Nimbus针对该拓扑创建本地的目录根据topology的配置计算task,分配task,在zookeeper上创建assignments节点存储task和supervisor机器节点中woker的对应关系;

在zookeeper上建立taskbeats节点来监控task的心跳;启动topology。

3) Supervisor去zookeeper上获取分配的tasks,启动多个woker进行,每一个woker生成task,一个task一个线程;根据topology信息初始化创建task之间的链接;Task和Task之间是经过zeroMQ管理的;后整个拓扑运行起来。

3.2 基于Yarn层面的架构

在YARN上开发一个应用程序,一般只须要开发两个组件,分别是客户端和ApplicationMaster,其中客户端主要做用是提交应用程序到YARN上,并和YARN和ApplicationMaster进行交互,完成用户发送的一些指令;而ApplicationMaster则负责向YARN申请资源,并与NodeManager通讯,启动任务。

不修改任何Storm源代码便可将其运行在YARN之上,最简单的实现方法是将Storm的各个服务组件(包括Nimbus和Supervisor)做为单独的任务运行在YARN上,而Zookeeper做为一个公共的服务运行在YARN集群以外的几个节点上。

1)经过YARN-Storm Client将Storm Application提交到YARN的RM上;

2)RM为YARN-Storm ApplicationMaster申请资源,并将其运行在一个节点上(Nimbus);

3)YARN-Storm ApplicationMaster 在本身内部启动Nimbus和UI服务;

4)YARN-Storm ApplicationMaster 根据用户配置向RM申请资源,并在申请到的Container中启动Supervisor服务;

5)与向普通Storm集群提交Topology同样,用户直接与运行在Nimbus交互,提交Topology。

3.3组件栈

3.4 特性分析

简单的编程模型。

相似于MapReduce下降了并行批处理复杂性,Storm下降了进行实时处理的复杂性。

服务化

一个服务框架,支持热部署,即时上线或下线App.

可使用各类编程语言

你能够在Storm之上使用各类编程语言。默认支持Clojure、Java、Ruby和Python。要增长对其余语言的支持,只需实现一个简单的Storm通讯协议便可。

容错性

Storm会管理工做进程和节点的故障。

水平扩展

计算是在多个线程、进程和服务器之间并行进行的。

可靠的消息处理

Storm保证每一个消息至少能获得一次完整处理。任务失败时,它会负责从消息源重试消息。

快速

系统的设计保证了消息能获得快速的处理,使用ZeroMQ做为其底层消息队列。

本地模式

Storm有一个“本地模式”,能够在处理过程当中彻底模拟Storm集群。这让你能够快速进行开发和单元测试。

部署性

依赖于Zookeeper进行任务状态的维护,必须首先部署Zookeeper。



4.三种框架的对比分析

Apache

Flink

SparkStreaming

Storm

架构

架构介于spark和storm之间,主从结构与spark streaming类似,DataFlow Grpah与Storm类似,数据流能够被表示为一个有向图。 每一个顶点是一个用户定义的运算,每向边表示数据的流动。

Native

架构依赖spark,主从模式,每一个Batch处理都依赖主(driver),能够理解为时间维度上的spark DAG。

Micro-Batch

主从模式,且依赖ZK,处理过程当中对主的依赖不大。

Native

容错

基于Chandy-Lamport distributed snapshots checkpoint机制

Medium

WAL及RDD 血统机制

High

Records ACK

Medium

处理模型与延迟

单条事件处理

亚秒级低延迟

一个事件窗口内的全部事件。

秒级高延迟

每次传入的一个事件

亚秒级低延迟

吞吐量

High

High

Low

数据处理保证

exactly once

High

exactly once(实现采用Chandy-Lamport 算法,即marker-checkpoint )

High

at least once(实现采用record-level acknowledgments),Trident能够支持storm 提供exactly once语义。

Medium

高级API

Flink 栈中提供了提供了不少具备高级 API 和知足不一样场景的类库:机器学习、图分析、关系式数据处理

High

可以很容易的对接Spark生态栈里面的组件,同时可以对接主流的消息传输组件及存储系统。

High

应用须要按照特定的storm定义的规则编写。

Low

易用性

支持SQL Steaming,Batch和STREAMING采用统一编程框架

High

支持SQL Steaming

Batch和STREAMING采用统一编程框架。

High

不支持SQL Steaming

Low

成熟性

新兴项目,处于发展阶段。

Low

已经发展一段时间

Medium

相对较早的流系统,比较稳定。

High

社区活跃度

212 contributor,活跃度呈上升趋势。

Medium

937 contirbutor

High

216 contributors,活跃度比较稳定。

Medium

部署性

部署相对简单,只依赖JRE环境

Low

部署相对简单,只依赖JRE环境

Low

依赖JRE环境和Zookeeper

High

对比分析

若是对延迟要求不高的状况下,建议使用Spark Streaming,丰富的高级API,使用简单,自然对接Spark生态栈中的其余组件,吞吐量大,部署简单,UI界面也作的更加智能,社区活跃度较高,有问题响应速度也是比较快的,比较适合作流式的ETL,并且Spark的发展势头也是有目共睹的,相信将来性能和功能将会更加完善。

若是对延迟性要求比较高的话,建议能够尝试下Flink,Flink是目前发展比较火的一个流系统,采用原生的流处理系统,保证了低延迟性,在API和容错上也是作的比较完善,使用起来相对来讲也是比较简单的,部署容易,并且发展势头也愈来愈好,相信后面社区问题的响应速度应该也是比较快的。


我的对Flink是比较看好的,由于原生的流处理理念,在保证了低延迟的前提下,性能仍是比较好的,且愈来愈易用,社区也在不断发展。


免费体验云安全(易盾)内容安全、验证码等服务

更多网易技术、产品、运营经验分享请点击




相关文章:
【推荐】 关于Runtime.getRuntime().exec()产生阻塞的2个陷阱

相关文章
相关标签/搜索