转载:https://www.cnblogs.com/Jack47/p/storm_intro-1.htmlhtml
本文是Storm系列之一,介绍了Storm的起源,Storm做者的八卦,Storm的特色和Storm模型的基本原理,着重介绍了Storm中的基本概念(Spout, Bolt, Stream, Tuple等)和对应的编程接口,能够做为Storm的入门文档来阅读。java
以前的技术文章都写的有点一板一眼,太正经了。今天在文章正式开始前,跟你们八卦一下Storm的做者Nathan Marz吧。web
Storm的做者是Nathan Marz,Nathan Marz在BackType公司工做的时候有了Storm的点子并独自一人实现了Storm。在2011年Twitter准备收购BackType之际,Nathan Marz为了提升Twitter对BackType的估值,在一篇博客里向外界介绍了Storm。Twitter对这项技术很是感兴趣,所以在Twitter收购BackType的时候Storm发挥了重大做用。后来Nathan Marz开源Storm时,也借着Twitter的品牌影响力而让Storm名声大震!算法
Storm的特色之一是可靠的消息处理机制,这个机制中最重要的一环是设计一个算法来跟踪Storm中处理的数据,确保Storm知道消息是否被完整的处理。他创造出的这个算法,极大的简化了系统的设计。Nathan Marz说这算法是他职业生涯中开发的最出色的算法之一,也说明了受过良好的计算机科学的教育是很是重要的。有趣的是发明这个算法的那天,正好是他和不久前遇到的一个姑娘约会的日子。当天由于发明了这个算法而很是兴奋,致使他心思一直在这个算法上,毫无疑问就搞砸了和这个姑娘的约会!数据库
Storm官方网站有段简介apache
Storm是一个免费并开源的分布式实时计算系统。利用Storm能够很容易作到可靠地处理无限的数据流,像Hadoop批量处理大数据同样,Storm能够实时处理数据。Storm简单,可使用任何编程语言。编程
在Storm以前,进行实时处理是很是痛苦的事情: 须要维护一堆消息队列和消费者,他们构成了很是复杂的图结构。消费者进程从队列里取消息,处理完成后,去更新数据库,或者给其余队列发新消息。api
这样进行实时处理是很是痛苦的。咱们主要的时间都花在关注往哪里发消息,从哪里接收消息,消息如何序列化,真正的业务逻辑只占了源代码的一小部分。一个应用程序的逻辑运行在不少worker上,但这些worker须要各自单独部署,还须要部署消息队列。最大问题是系统很脆弱,并且不是容错的:须要本身保证消息队列和worker进程工做正常。数组
Storm完整地解决了这些问题。它是为分布式场景而生的,抽象了消息传递,会自动地在集群机器上并发地处理流式计算,让你专一于实时处理的业务逻辑。安全
Storm有以下特色:
不过Storm不是一个完整的解决方案。使用Storm时你须要关注如下几点:
跟Hadoop不同,Storm是没有包括任何存储概念的计算系统。这就让Storm能够用在多种不一样的场景下:非传统场景下数据动态到达或者数据存储在数据库这样的存储系统里(或数据是被实时操控其余设备的控制器(如交易系统)所消费)
Storm有不少应用:实时分析,在线机器学习(online machine learning),连续计算(continuous computation),分布式远程过程调用(RPC)、ETL等。Storm处理速度很快:每一个节点每秒钟能够处理超过百万的数据组。它是可扩展(scalable),容错(fault-tolerant),保证你的数据会被处理,而且很容易搭建和操做。
例如Nathan Marz提供的例子,产生Twitter的趋势信息。Twitter从海量推文中抽取趋势信息,并在本地区域和国家层级进行维护。这意味者一旦一个案例开始出现,Twitter的话题趋势算法就能实时的鉴别出这个话题。这个实时的算法就是经过在Storm上连续分析Twitter数据来实现的。
下表列出了一组开源的大数据解决方案,包括传统的批处理和流式处理的应用程序。
解决方案 | 开发者 | 类型 | 描述 |
---|---|---|---|
Storm | 流式处理 | Twitter的流式处理大数据分析方案 | |
S4 | Yahoo! | 流式处理 | Yahoo!的分布式流式计算平台 |
Hadoop | Apache | 批处理 | MapReduce范式的第一个开源实现 |
Spark | UC Berkeley AMPLab | 批处理 | 支持内存数据集和弹性恢复的分析平台 |
Yahoo! S4和Storm之间的关键差异是Storm在故障的状况下能够保证消息的处理,而S4可能会丢消息。
Hadoop无疑是大数据分析的王者,本质上是一个批量处理系统,它专一于大数据的批量处理。数据存储在Hadoop 文件系统里(HDFS)并在处理的时候分发到集群中的各个节点。当处理完成,产出的数据放回到HDFS上。在Storm上构建的拓扑处理的是持续不断的流式数据。不一样于Hadoop的任务,这些处理过程不会终止,会持续处理到达的数据。
Hadoop处理的是静态的数据,而Storm处理的是动态的、连续的数据。Twitter的用户天天都会发上千万的推,因此这种处理技术是很是有用的。Storm不只仅是一个传统的大数据分析系统:它是一个复琐事件(complex event-processing)处理系统的例子。复琐事件处理系统一般是面向检测和计算的,这两部分均可以经过用户定义的算法在Storm中实现。例如,复琐事件处理能够用来从大量的事件中区分出有意义的事件,而后对这些事件实时处理。
Storm实现了一个数据流(data flow)的模型,在这个模型中数据持续不断地流经一个由不少转换实体构成的网络。一个数据流的抽象叫作流(stream),流是无限的元组(Tuple)序列。元组就像一个能够表示标准数据类型(例如int,float和byte数组)和用户自定义类型(须要额外序列化代码的)的数据结构。每一个流由一个惟一的ID来标示的,这个ID能够用来构建拓扑中各个组件的数据源。
以下图所示,其中的水龙头表明了数据流的来源,一旦水龙头打开,数据就会源源不断地流经Bolt而被处理。图中有三个流,用不一样的颜色来表示,每一个数据流中流动的是元组(Tuple),它承载了具体的数据。元组经过流经不一样的转换实体而被处理。
Storm对数据输入的来源和输出数据的去向没有作任何限制。像Hadoop,是须要把数据放到本身的文件系统HDFS里的。在Storm里,可使用任意来源的数据输入和任意的数据输出,只要你实现对应的代码来获取/写入这些数据就能够。典型场景下,输入/输出数据来是基于相似Kafka或者ActiveMQ这样的消息队列,可是数据库,文件系统或者web服务也都是能够的。
Storm中涉及的主要概念有:
能够看到Storm中各个概念的名字起的很是好,也很形象。
一个Storm拓扑打包了一个实时处理程序的逻辑。一个Storm拓扑跟一个MapReduce的任务(job)是相似的。主要区别是MapReduce任务最终会结束,而拓扑会一直运行(固然直到你杀死它)。一个拓扑是一个经过流分组(stream grouping)把Spout和Bolt链接到一块儿的拓扑结构。图的每条边表明一个Bolt订阅了其余Spout或者Bolt的输出流。一个拓扑就是一个复杂的多阶段的流计算。
元组是Storm提供的一个轻量级的数据格式,能够用来包装你须要实际处理的数据。元组是一次消息传递的基本单元。一个元组是一个命名的值列表,其中的每一个值均可以是任意类型的。元组是动态地进行类型转化的--字段的类型不须要事先声明。在Storm中编程时,就是在操做和转换由元组组成的流。一般,元组包含整数,字节,字符串,浮点数,布尔值和字节数组等类型。要想在元组中使用自定义类型,就须要实现本身的序列化方式。
流是Storm中的核心抽象。一个流由无限的元组序列组成,这些元组会被分布式并行地建立和处理。经过流中元组包含的字段名称来定义这个流。
每一个流声明时都被赋予了一个ID。只有一个流的Spout和Bolt很是常见,因此OutputFieldsDeclarer
提供了不须要指定ID来声明一个流的函数(Spout和Bolt都须要声明输出的流)。这种状况下,流的ID是默认的“default”。
Spout(喷嘴,这个名字很形象)是Storm中流的来源。一般Spout从外部数据源,如消息队列中读取元组数据并吐到拓扑里。Spout能够是可靠的(reliable)或者不可靠(unreliable)的。可靠的Spout可以在一个元组被Storm处理失败时从新进行处理,而非可靠的Spout只是吐数据到拓扑里,不关心处理成功仍是失败了。
Spout能够一次给多个流吐数据。此时须要经过OutputFieldsDeclarer
的declareStream
函数来声明多个流并在调用SpoutOutputCollector
提供的emit
方法时指定元组吐给哪一个流。
Spout中最主要的函数是nextTuple
,Storm框架会不断调用它去作元组的轮询。若是没有新的元组过来,就直接返回,不然把新元组吐到拓扑里。nextTuple
必须是非阻塞的,由于Storm在同一个线程里执行Spout的函数。
Spout中另外两个主要的函数是ack
和fail
。当Storm检测到一个从Spout吐出的元组在拓扑中成功处理完时调用ack
,没有成功处理完时调用fail
。只有可靠型的Spout会调用ack
和fail
函数。更多细节能够查看Storm Java文档和个人另一篇文章:Storm如何保证可靠的消息处理
在拓扑中全部的计算逻辑都是在Bolt中实现的。一个Bolt能够处理任意数量的输入流,产生任意数量新的输出流。Bolt能够作函数处理,过滤,流的合并,聚合,存储到数据库等操做。Bolt就是流水线上的一个处理单元,把数据的计算处理过程合理的拆分到多个Bolt、合理设置Bolt的task数量,可以提升Bolt的处理能力,提高流水线的并发度。
Bolt能够给多个流吐出元组数据。此时须要使用OutputFieldsDeclarer
的declareStream
方法来声明多个流并在使用[OutputColletor](https://storm.apache.org/javadoc/apidocs/backtype/storm/task/OutputCollector.html)
的emit
方法时指定给哪一个流吐数据。
当你声明了一个Bolt的输入流,也就订阅了另一个组件的某个特定的输出流。若是但愿订阅另外一个组件的全部流,须要单独挨个订阅。InputDeclarer有语法糖来订阅ID为默认值的流。例如declarer.shuffleGrouping("redBolt")
订阅了redBolt组件上的默认流,跟declarer.shuffleGrouping("redBolt", DEFAULT_STREAM_ID)
是相同的。
在Bolt中最主要的函数是execute
函数,它使用一个新的元组看成输入。Bolt使用OutputCollector
对象来吐出新的元组。Bolts必须为处理的每一个元组调用OutputCollector
的ack
方法以便于Storm知道元组何时被各个Bolt处理完了(最终就能够确认Spout吐出的某个元组处理完了)。一般处理一个输入的元组时,会基于这个元组吐出零个或者多个元组,而后确认(ack)输入的元组处理完了,Storm提供了IBasicBolt接口来自动完成确认。
必须注意OutputCollector
不是线程安全的,因此全部的吐数据(emit)、确认(ack)、通知失败(fail)必须发生在同一个线程里。更多信息能够参照问题定位。
每一个Spout和Bolt会以多个任务(Task)的形式在集群上运行。每一个任务对应一个执行线程,流分组定义了如何从一组任务(同一个Bolt)发送元组到另一组任务(另一个Bolt)上。能够在调用TopologyBuilder
的setSpout
和setBolt
函数时设置每一个Spout和Bolt的并发数。
组件(component)是对Bolt和Spout的统称
定义拓扑的时候,一部分工做是指定每一个Bolt应该消费哪些流。流分组定义了一个流在一个消费它的Bolt内的多个任务(task)之间如何分组。流分组跟计算机网络中的路由功能是相似的,决定了每一个元组在拓扑中的处理路线。
在Storm中有七个内置的流分组策略,你也能够经过实现CustomStreamGrouping
接口来自定义一个流分组策略:
emitDirect
系列函数来吐元组给直连流。一个Bolt能够经过提供的TopologyContext
来得到消费者的任务ID,也能够经过OutputCollector对象的emit
函数(会返回元组被发送到的任务的ID)来跟踪消费者的任务ID。在ack的实现中,Spout有两个直连输入流,ack和ackFail,使用了这种直连分组的方式。TopologyBuilder
的setBolt
函数时会返回这个对象,它用来声明一个Bolt的输入流并指定流的分组方式。Storm保证了拓扑中Spout产生的每一个元组都会被处理。Storm是经过跟踪每一个Spout所产生的全部元组构成的树形结构并得知这棵树什么时候被完整地处理来达到可靠性。每一个拓扑对这些树形结构都有一个关联的“消息超时”。若是在这个超时时间里Storm检测到Spout产生的一个元组没有被成功处理完,那Sput的这个元组就处理失败了,后续会从新处理一遍。
为了发挥Storm的可靠性,须要你在建立一个元组树中的一条边时告诉Storm,也须要在处理完每一个元组以后告诉Storm。这些都是经过Bolt吐元组数据用的OutputCollector
对象来完成的。标记是在emit
函数里完成,完成一个元组后须要使用ack
函数来告诉Storm。
这些都在“保证消息处理”一文中会有更详细的介绍。
拓扑以一个或多个Worker进程的方式运行。每一个Worker进程是一个物理的Java虚拟机,执行拓扑的一部分任务。例如,若是拓扑的并发设置成了300,分配了50个Worker,那么每一个Worker执行6个任务(做为Worker内部的线程)。Storm会尽可能把全部的任务均分到全部的Worker上。
ZeroMQ 提供了可扩展环境下的传输层高效消息通讯,一开始Storm的内部通讯使用的是ZeroMQ,后来做者想把Storm移交给Apache开源基金会来管理,而ZeroMQ的许可证书跟Apache基金会的政策有冲突。在Storm中,Netty比ZeroMQ更加高效,并且提供了worker间通讯时的验证机制,因此在Storm0.9中,就改用了Netty。
Clojure Storm系统的实现语言。Clojure是由Rich Hicky做为一种通用语言发明的,它衍生自Lisp语言,简化了多线程编程。
Apache ZooKeeper Zookeeper是一个实现高可靠的分布式协做的开源项目。Storm使用Zookeeper来协调集群中的多个节点。
Storm简介 这是淘宝主搜索的技术博客,文章通俗易懂
History of Apache Storm and lessons learned 推荐你们读一读,是Storm做者Nathan Marz写的,文章讲述了Storm的构思、建立过程和Storm的市场营销,沟通交流和社区开发的故事。
twitter storm --IBM developerworks