You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
12 KiB
Markdown

2 years ago
# 15 | 流式计算的代表Storm、Flink、Spark Streaming
我前面介绍的大数据技术主要是处理、计算存储介质上的大规模数据这类计算也叫大数据批处理计算。顾名思义数据是以批为单位进行计算比如一天的访问日志、历史上所有的订单数据等。这些数据通常通过HDFS存储在磁盘上使用MapReduce或者Spark这样的批处理大数据计算框架进行计算一般完成一次计算需要花费几分钟到几小时的时间。
此外还有一种大数据技术针对实时产生的大规模数据进行即时计算处理我们比较熟悉的有摄像头采集的实时视频数据、淘宝实时产生的订单数据等。像上海这样的一线城市公共场所的摄像头规模在数百万级即使只有重要场所的视频数据需要即时处理可能也会涉及几十万个摄像头如果想实时发现视频中出现的通缉犯或者违章车辆就需要对这些摄像头产生的数据进行实时处理。实时处理最大的不同就是这类数据跟存储在HDFS上的数据不同是实时传输过来的或者形象地说是流过来的所以针对这类大数据的实时处理系统也叫大数据流计算系统。
目前业内比较知名的大数据流计算框架有Storm、Spark Streaming、Flink接下来我们逐一看看它们的架构原理与使用方法。
## Storm
其实大数据实时处理的需求早已有之,最早的时候,我们用消息队列实现大数据实时处理,如果处理起来比较复杂,那么就需要很多个消息队列,将实现不同业务逻辑的生产者和消费者串起来。这个处理过程类似下面图里的样子。
![](https://static001.geekbang.org/resource/image/19/31/199c65da1a9dfae48f42c32f6a82c831.png)
图中的消息队列负责完成数据的流转;处理逻辑既是消费者也是生产者,也就是既消费前面消息队列的数据,也为下个消息队列产生数据。这样的系统只能是根据不同需求开发出来,并且每次新的需求都需要重新开发类似的系统。因为不同应用的生产者、消费者的处理逻辑不同,所以处理流程也不同,因此这个系统也就无法复用。
之后我们很自然地就会想到能不能开发一个流处理计算系统我们只要定义好处理流程和每一个节点的处理逻辑代码部署到流处理系统后就能按照预定义的处理流程和处理逻辑执行呢Storm就是在这种背景下产生的它也算是一个比较早期的大数据流计算框架。上面的例子如果用Storm来实现过程就变得简单一些了。
![](https://static001.geekbang.org/resource/image/78/5b/780899b3fda0ea39acbdfb9545fbc55b.png)
有了Storm后开发者无需再关注数据的流转、消息的处理和消费只要编程开发好数据处理的逻辑bolt和数据源的逻辑spout以及它们之间的拓扑逻辑关系toplogy提交到Storm上运行就可以了。
在了解了Storm的运行机制后我们来看一下它的架构。Storm跟Hadoop一样也是主从架构。
![](https://static001.geekbang.org/resource/image/d3/8a/d33aa8765ad381824fd9818f93074a8a.png)
nimbus是集群的Master负责集群管理、任务分配等。supervisor是Slave是真正完成计算的地方每个supervisor启动多个worker进程每个worker上运行多个task而task就是spout或者bolt。supervisor和nimbus通过ZooKeeper完成任务分配、心跳检测等操作。
Hadoop、Storm的设计理念其实是一样的就是把和具体业务逻辑无关的东西抽离出来形成一个框架比如大数据的分片处理、数据的流转、任务的部署与执行等开发者只需要按照框架的约束开发业务逻辑代码提交给框架执行就可以了。
而这也正是所有框架的开发理念就是将业务逻辑和处理过程分离开来使开发者只需关注业务开发即可比如Java开发者都很熟悉的Tomcat、Spring等框架全部都是基于这种理念开发出来的。
## Spark Streaming
我们知道Spark是一个批处理大数据计算引擎主要针对大批量历史数据进行计算。前面我在讲Spark架构原理时介绍过Spark是一个快速计算的大数据引擎它将原始数据分片后装载到集群中计算对于数据量不是很大、过程不是很复杂的计算可以在秒级甚至毫秒级完成处理。
Spark Streaming巧妙地利用了Spark的**分片**和**快速计算**的特性将实时传输进来的数据按照时间进行分段把一段时间传输进来的数据合并在一起当作一批数据再去交给Spark去处理。下图这张图描述了Spark Streaming将数据分段、分批的过程。
![](https://static001.geekbang.org/resource/image/fb/c3/fb535e9dc1813dbacfa03c7cb65d17c3.png)
如果时间段分得足够小每一段的数据量就会比较小再加上Spark引擎的处理速度又足够快这样看起来好像数据是被实时处理的一样这就是Spark Streaming实时流计算的奥妙。
这里要注意的是在初始化Spark Streaming实例的时候需要指定分段的时间间隔。下面代码示例中间隔是1秒。
```
val ssc = new StreamingContext(conf, Seconds(1))
```
当然你也可以指定更小的时间间隔比如500ms这样处理的速度就会更快。时间间隔的设定通常要考虑业务场景比如你希望统计每分钟高速公路的车流量那么时间间隔可以设为1分钟。
Spark Streaming主要负责将流数据转换成小的批数据剩下的就可以交给Spark去做了。
## Flink
前面说Spark Streaming是将实时数据流按时间分段后当作小的批处理数据去计算。那么Flink则相反一开始就是按照流处理计算去设计的。当把从文件系统HDFS中读入的数据也当做数据流看待他就变成批处理系统了。
为什么Flink既可以流处理又可以批处理呢
如果要进行流计算Flink会初始化一个流执行环境StreamExecutionEnvironment然后利用这个执行环境构建数据流DataStream。
```
StreamExecutionEnvironment see = StreamExecutionEnvironment.getExecutionEnvironment();
DataStream<WikipediaEditEvent> edits = see.addSource(new WikipediaEditsSource());
```
如果要进行批处理计算Flink会初始化一个批处理执行环境ExecutionEnvironment然后利用这个环境构建数据集DataSet。
```
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
DataSet<String> text = env.readTextFile("/path/to/file");
```
然后在DataStream或者DataSet上执行各种数据转换操作transformation这点很像Spark。不管是流处理还是批处理Flink运行时的执行引擎是相同的只是数据源不同而已。
Flink处理实时数据流的方式跟Spark Streaming也很相似也是将流数据分段后一小批一小批地处理。流处理算是Flink里的“一等公民”Flink对流处理的支持也更加完善它可以对数据流执行window操作将数据流切分到一个一个的window里进而进行计算。
在数据流上执行
```
.timeWindow(Time.seconds(10))
```
可以将数据切分到一个10秒的时间窗口进一步对这个窗口里的一批数据进行统计汇总。
Flink的架构和Hadoop 1或者Yarn看起来也很像JobManager是Flink集群的管理者Flink程序提交给JobManager后JobManager检查集群中所有TaskManager的资源利用状况如果有空闲TaskSlot任务槽就将计算任务分配给它执行。
![](https://static001.geekbang.org/resource/image/92/9f/92584744442b15d541a355eb7997029f.png)
## 小结
大数据技术最开始出现的时候仅仅针对批处理计算也就是离线计算。相对说来大数据实时计算可以复用互联网实时在线业务的处理技术方案毕竟对于Google而言每天几十亿的用户搜索访问请求也是大数据而互联网应用处理实时高并发请求已经有一套完整的解决方案了详见我写的《大型网站技术架构核心原理与案例分析》一书大数据流计算的需求当时并不强烈。
但是我们纵观计算机软件发展史,发现这部历史堪称一部**技术和业务不断分离**的历史。人们不断将业务逻辑从技术实现上分离出来,各种技术和架构方案的出现,也基本都是为这一目标服务。
最早的时候我们用机器语言和汇编语言编程直接将业务逻辑用CPU指令实现计算机软件就是CPU指令的集合此时技术和业务完全耦合软件编程就是面向机器编程用机器指令完成业务逻辑当时我们在编程的时候思维方式是面向机器的需要熟记机器指令。
后来我们有了操作系统和高级编程语言将软件和CPU指令分离开来我们使用Pascal、Cobal这样的高级编程语言进行编程并将程序运行在操作系统上。这时我们不再面向机器编程而是面向业务逻辑和过程编程这是业务逻辑与计算机技术的一次重要分离。
再后来出现了面向对象的编程语言,这是人类编程史上的里程碑。我们编程的时候关注的重心,从机器、业务过程转移到业务对象本身,分析客观世界业务对象的关系和协作是怎样的,如何通过编程映射到软件上,这是编程思维的一次革命,业务和技术实现从思想上分离了。
再后来出现各种编程框架一方面使业务和技术分离得更加彻底想象一下如果不用这些框架你自己编程监听80通信端口从获取HTTP二进制流开始到开发一个Web应用会是什么感觉。另一方面这些框架也把复杂的业务流程本身解耦合视图、业务、服务、存储各个层次模块独立开发、部署通过框架整合成一个系统。
回到流计算,固然我们可以用各种分布式技术实现大规模数据的实时流处理,但是我们更希望只要针对小数据量进行业务开发,然后丢到一个大规模服务器集群上,就可以对大规模实时数据进行流计算处理。也就是业务实现和大数据流处理技术分离,业务不需要关注技术,于是各种大数据流计算技术应运而生。
其实我们再看看互联网应用开发也是逐渐向业务和技术分离的方向发展。比如云计算以云服务的方式将各种分布式解决方案提供给开发者使开发者无需关注分布式基础设施的部署和维护。目前比较热门的微服务、容器、服务编排、Serverless等技术方案它们则更进一步使开发者只关注业务开发将业务流程、资源调度和服务管理等技术方案分离开来。而物联网领域时髦的FaaS意思是函数即服务就是开发者只要开发好函数提交后就可以自动部署到整个物联网集群运行起来。
总之,流计算就是将大规模实时计算的资源管理和数据流转都统一管理起来,开发者只要开发针对小数据量的数据处理逻辑,然后部署到流计算平台上,就可以对大规模数据进行流式计算了。
## 思考题
流计算架构方案也逐渐对互联网在线业务开发产生影响,目前流行的微服务架构虽然将业务逻辑拆分得很细,但是服务之间的调用还是依赖接口,这依然是一种比较强的耦合关系。淘宝等互联网企业已经在尝试一种类似流计算的、异步的、基于消息的服务调用与依赖架构,据说淘宝的部分核心业务功能已经使用这种架构方案进行系统重构,并应用到今年的“双十一”大促,利用这种架构特有的回压设计对高并发系统进行自动限流与降级,取得很好的效果。
我也邀请了淘宝负责这次架构重构的高级技术专家李鼎,请他在留言区分享一下这次架构重构的心得体会。
你对这种架构方案有什么想法,是否认为这样的架构方案代表了未来的互联网应用开发的方向?
欢迎你写下自己的思考或疑问,与我和其他同学一起讨论。