叁叁肆

这个世界会好吗

453篇博客

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

叁叁肆2018-10-31 13:50

此文已由作者岳猛授权网易云社区发布。

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

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 任务没有任何区别。

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,易于编程。

广泛集成

除了可以读取HDFSFlumeKafkaTwitter 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是比较看好的,因为原生的流处理理念,在保证了低延迟的前提下,性能还是比较好的,且越来越易用,社区也在不断发展。


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

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




相关文章:
【推荐】 白木彰:具有普遍性的设计力
【推荐】 virtualenv简介以及一个比较折腾的scrapy安装方法
【推荐】 透过数据看真相:手游市场趋势报告