Storm是一个分布式、高容错、高可靠性的实时计算系统,它对于实时计算的意义至关于Hadoop对于批处理的意义。Hadoop提供了Map和Reduce原语。一样,Storm也对数据的实时处理提供了简单的数据库
spout和bolt原语。Storm集群表面上看和Hadoop集群很是像,但Hadoop上面运行的是MapReduce的Job,而Storm上面运行的是topology(拓扑),它们很是不同,好比一个MapReduce的Job最终会结束,数组
而一个Storm topology永远运行(除非显式杀掉它)服务器
topology网络
一个事实应用程序在Storm中称为一个拓扑(topology), Storm中的拓扑相似于Hadoop的MapReduce任务,不一样之处是,一个MapReduce任务总会运行完成,而拓扑若是不显式结束则一直运行。架构
一个Storm拓扑通常由一个或者多个spout(负责发送消息)以及一个或者多个bol(负责处理消息)作组成。并发
tuple负载均衡
Storm处理的基本消息单元为tuple(元组),Tuple是一个明明值列表,元组中的字段能够是任何类型的对象。Storm用元组做为其数据模型,元组支持全部基本类型、字符串和字节数组做为字段值,框架
只要实现类型的序列化接口,就可使用该类型的对象。元组是一个值的列表。分布式
流函数
流(Stream)在Storm中是一个核心抽象概念。一个流是由无数个元组序列构成,这些元组并行、分布式的被建立和执行。在stream的许多元组中,Streams被定义为以Fields区域命名的一种模式。
默认状况下,元组支持:Integers,longs,shorts,bytes,strings,doubles,floats,booleans,and byte arrays.
每个Stream在声明的时候都会赋予一个id,单个Stream--spouts和bolts,可使用OutputFieldsDeclarer的convenience方法声明一个stream.而不用指定一个id,可是这种方法会给一个模式的id: default。
spout
spout(喷口)是topology的流的来源,是一个topology中产生源数据流的组件。一般状况下,spout会从外表数据源(例如kafak队列或Tiwitter API)中读取数据,而后转为为topology 内部的源数据。
spout能够是可靠是,也能够是不可靠的。若是Storm处理元组失败,可靠的spout可以从新发射,不可靠的spout没法从新发射已经发出的元组。spout是一个主动的角色,其接口中有一个nextTuple()函数,
Storm框架会不停的调用此函数,用户只要在其中生成源数据便可。
spout能够发出超过一个的流。为此,使用OutputFieldsDeclarer类的declareStream方法来声明多个流,使用SpoutOutputCollector类的emit执行方法来进行流的提交。
spout的主要方法是nextTuple(),nextTuple()会发出一个新的tuple到拓扑,若是没有新的元组发出,则简单地返回。nextTuple()方法不阻止任何的spout的实现,由于stream在同一个线程调用全部
spout方法。
spout的其它主要方法是ack()和fail(). 当Storm监测到一个tuple从spout发出时,ack()和fail()会被调用,要么成功完成经过拓扑,要么未能完成。ack()和fail()仅被可靠的spout调用。IRichSpout是 spout
必须实现的接口。
bolt
拓扑中全部处理逻辑都在bolt(螺栓)中完成,bolt是流的处理节点,从一个拓扑接收数据后执行进行出来的 组件。bolt能够完成过滤(filter)、业务处理。链接运算(join)、链接与访问数据库的等任何操做。
bolt是一个被动的角色,其接口中只有一个execute()方法,此方法在接收到消息后会被调用,用户能够在其中执行本身但愿的操做。
bolt能够完成简单的流的转换,而完成复杂的流的转换一般须要多个步骤,所以须要多个bolt。此外,bolt也能够发出超过一个的流。
bolt的主要方法是execute()方法,该方法将一个元组做为输入。bolt使用 OutputCollector对象发射新tuple。bolt必须为他们处理的每一个元组调用OutputCollector类的ack()方法,以便Storm只是什么
时候元组会完成。
流分组
定义一个topology的步骤之一是定义每一个bolt接收什么样的流做为输入。流分组(stream grouping)用来定义一个Strream应该如何分配数据给bolts上的多个任务。
在Storm中,有8种内置流分组方式,经过实现CustomStreamGrouping接口,用户能够实现本身的流分组方式。
shuffle grouping(随机分组):这种方式会随机分发tuple给bolt的各个任务,每一个bolt实例接收相同数量的tuple。
fields grouping(字段分组):根据指定字段的值进行分组,例如,一个数据流根据“word”字段进行分组,全部具备相同"word"字段值的(tuple)会路由到同一个(bolt)的task中。
all grouping(全复制分组):将全部的tuple复制后分发给全部bolt task, 每一个订阅数据流的task都会接收到全部的tuple的一份备份。
globle grouping(全局分组):这种分组方式将全部的tuples路由到惟一的任务上,Storm按照最小的taskID来接收数据的task,注意,当使用全局分组方式时,设置bolt的task并发度是没有意义的(spout并发有意义),
由于全部的tuple都转发到一个task上了,此外,由于全部的tuple都转发到一个JVM实例上,可能会引发Storm集群中某个JVM或服务器出现性能瓶颈或崩溃。
none grouping(不分组):在功能上和随机分组相同,是为未来预留的。
direct grouping(指向性分组):数据源会调用emitDirect()方法来判断一个tuple应该由哪一个Storm组件来接收。
local or shuffle grouping(本地或随机分组):和随机分组相似,可是会将tuple分发给同一个worker内的bolt task(若是workder内有接收数据的bolt task),其它状况下,则采用随机分组的方式。本地或随机分组取决于
topology的并发度,能够减小网络传输,从而提升topology性能。
partial key grouping:与按字段分组相似,根据指定字段的一部分进行分组分发,可以很好的实现负载均衡,将元组发送给下游的bolt对应的任务,特别是存在数据倾斜的状况下,使用partial key grouping可以很好的
提升资源利用率。
Storm集群中真正运行topology的主要有三个实体:worker(工做进程),executor(线程)和task(任务)。
参考资料:《离线和实时大数据开发实战》