storm核心概念与整体框架

目录

1、Storm概述

2、Storm特点

3、集群架构与核心概念

3.1 主节点 Nimbus

3.2 工作节点 Supervisor 

3.3 协调服务组件 Zookeeper 

3.4 元组 Tuple

3.5 工作进程 Worker

3.6 线程 Task 

3.7 消息源 Spout 

3.8 数据处理 Bolt 

3.9 拓扑 Topology 

3.10 流分组Stream Grouping 

3.11 Ack机制

4、storm 整体框架

4.1 zookeeper中存放的数据

4.1.1 worker进程的状态及统计信息

4.1.2 Topology信息

4.1.3 Supervisor上的任务信息

4.1.4 Supervisor状态信息

4.1.5 错误日志

4.2 Nimbus

4.2.1 Nimbus创建的路径

4.2.2 Nimbus获取数据

4.3 Supervisors

4.3.1 Supervisors启动时注册节点

4.3.2 Supervisors获取任务信息

4.3.3 Supervisors检查worker心跳

4.4 worker

4.4.1 worker向zookeeper注册

4.4.2 worker拉取任务信息并执行

4.4.3 worker与supervisor通过本地文件传递心跳

4.5 Excutor


1、Storm概述

Storm 是一个实时的、分布式的、可靠的流式数据处理系统。它的工作就是委派各种组件分别独立的处理一些简单任务。在 Storm 集群中处理输入流的是 Spout 组件,而 Spout 又把读取的数据传递给叫Bolt 的组件。Bolt组件会对收到的数据元组进行处理,也有可能传递给下一个Bolt。我们可以把 Storm 集群想象成一个由Bolt 组件组成的链条集合,数据在这些链条上传输,而 Bolt作为链条上的节点来对数据进行处理。 

Storm 保证每个消息都会得到处理,而且处理速度非常快,在一个小集群中,每秒可以处理数以百万计的消息。Storm 的处理速度非常惊人:经测试,每个节点每秒可以处理 100 万个数据元组。其主要应用领域有实时分析、在线机器学习、持续计算、分布式 RPC(远过程调用协议,一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。)、ETL(数据抽取、转换和加载)等。

 Storm 和 Hadoop 集群表面看上去很类似,但是 Hadoop 上面运行的是 Map Reduce  Jobs,而在Storm 上运行的是拓扑 Topology,这两者之间是非常不一样的,关键区别是:Map Reduce 最终会结束,而一个 Topology 永远会运行(除非你手动 kill 掉),换句话说,Storm 是面向实时数据分析,而 Hadoop 面向的是离线数据分析。


2、Storm特点

2.1. 编程模型简单 
       在大数据处理方面,Hadoop 为开发者提供了 Map Reduce 原语,使并行批处理程序变得非常简单和优美。同样,Storm 也为大数据的实时计算提供了一些简单优美的原语,这大大降低了开发并行实时处理任务的复杂性,可以快速、高效的开发应用。 

2.2. 可扩展
       在 Storm 集群中真正运行 Topology 的主要有 3 个实体:工作进程、线程和任务。Storm 集群中的每台机器都可以运行多个工作进程,每个工作进程又可创建多个线程,每个线程可以执行多个任务,任务是真正进行数据处理的实体,开发的 Spout、Bolt 就是作为一个或者多个任务的方式执行的。因此,计算任务在多个线程、进程和服务器之间并行进行,支持灵活的水平扩展。

2.3. 高可靠性
       Spout 发出消息后,可能会触发产生成千上万条消息,可以形象地理解为一颗消息树,其中 Spout发出的消息为树根,Storm 会跟踪这颗消息树的处理情况,只有当这颗消息树中的所有消息都被处理了,Storm 才会认为 Spout 发出的这个消息已经被“完全处理”。如果这颗消息树种的任何一个消息处理失败了,或者整棵消息树在限定时间内没有“完全处理”,那么 Spout 发出的消息就会重发。

2.4. 高容错性
       如果在消息处理过程中出了一些异常,Storm 会重新安排这个出问题的处理单元。Storm 保证一个处理单元永远运行(除非显式杀掉该处理单元)。

2.5. 支持多种编程语言
       除了用 Java 实现 Spout 和 Bolt,还可以使用其他编程语言来完成这项工作,这一切得益于 Storm 的多语言协议。多语言协议是 Storm 内部的一种特殊协议,允许 Spout 或 Bolt 使用标准输入和标准输出来传递消息,传递的消息为单行文本或多行 JSON编码的格式。 

2.6. 支持本地模式
       Storm 有一种“本地模式”,也就是在进程中模拟一个 Storm 集群的所有功能,以本地模式运行Topology 与在集群上运行 Topology 类似,这对于开发和测试来说非常有用。 

 2.7. 高效
      用 Zero MQ 作为底层消息队列,保证消息能被快速处理。 


3、集群架构与核心概念

Storm 的集群由一个主节点和多个工作节点组成。主节点运行一个名为“Nimbus”的守护进程,每个工作节点都运行一个名为“Supervisor”的守护进程,两者的协调工作由 Zoo Keeper 来完成,ZooKeeper 用于管理集群中的不同组件。

storm集群架构

3.1 主节点 Nimbus

主节点通常运行一个后台程序——Nimbus,用于响应分布在集群中的节点,分配任务和监测故障,在某个节点的 Supervisor 出现故障宕机之后,如果在该节点上运行的 Worker 进程异常终止,Nimbus会将异常终止的 Worker 进程分配到其他 Supervisor 节点上继续运行,这类似于 Hadoop 中的Job Tracker。

3.2 工作节点 Supervisor 

每一个工作节点上面运行一个叫做 Supervisor 的守护进程。Supervisor 负责监听从 Nimbus 分配给它执行的任务,还能保证正常运行的 Worker 异常终止之后能够重启该 Worker。Nimbus 和 Supervisor 之间的协调则通过 Zoo Keeper 系统。 

3.3 协调服务组件 Zookeeper 

ZooKeeper 是完成 Nimbus 和 Supervisor 之间协调的服务。而应用程序实现实时的逻辑则被封装进Storm 中的“topology”。Topology 则是一组由 Spout(数据源)和 Bolts(数据处理)通过 Stream Groupings 进行连接的图。 

3.4 元组 Tuple

一次消息传递的基本单元。本来应该是一个 key-value 的 map,但是由于各个组件间传递的 tuple 的字段名称已经事先定义好,所以 tuple 中只要按序填入各个 value 就行了,所以就是一个值列表,如下图(添加图片失败,暂无)。 

3.5 工作进程 Worker

位于工作节点 (Supervisor )上,Worker 是一个 Java 进程,执行拓扑的一部分任务。一个 Worker 进程执行一个 Topology 的子集(一个进程只能执行一个拓扑的子集),它会启动一个或多个 Executor 线程来执行一个 Topology 的组件(Spout 或 Bolt)。(但是一个Executor 线程可能执行多个相同的组件)。

3.6 线程 Task 

Task 是运行 Spout 和 Bolt 的单元,每一个 Spout/Bolt 的线程称为一个 Task。在 Storm0.8 之后的版本中,Task 不再与物理线程对应,同一个 Spout/Bolt 的 Task 可能会共享一个物理线程(一个物理线程可能执行多个相同的task),该线程称为Executor。

3.7 消息源 Spout 

消息源 Spout 是 Storm 的 Topology 中的消息生产者(即 Tuple 的创建者)。Spout 向 Topology 中发出的 Tuple 可以是可靠地,也可以是不可靠的。当 Storm 接收失败时,可靠地 Spout 会对 Tuple 进行重发。而不可靠的 Spout 不会考虑成功是否只发射一次。

消息源可以发射多条消息流 Stream,使用OutputFieldsDeclarer.declareStream 来定义多个 Stream,然后使用 SpoutOutputCollector 来发射指定的 Stream。

Spout 中最主要的方法就是 next Tuple(),该方法会发射一个新的 Tuple 到 Topology,如果没有新 Tuple 发射则会简单地返回。要注意的是 nextTuple 方法不能阻塞,因为 Storm 在同一个线程上面调用所有消息源 Spout 方法。

另外两个比较重要的 Spout 方法是 ack 和 fail。Storm 在检测到一个 Tuple 被整个 Topology成功处理的时候调用 ack,否则调用 fail。Storm 只对可靠的 Spout 调用 ack 和 fail。

open方法是初始化动作。允许你在该spout初始化时做一些动作,传入了上下文,方便取上下文的一些数据。

close方法在该spout关闭前执行,但是并不能得到保证其一定被执行。spout是作为task运行在worker内,
在cluster模式下,supervisor会直接kill -9 woker的进程,这样它就无法执行了。而在本地模式下,
只要不是kill -9, 如果是发送停止命令,是可以保证close的执行的。

activate和deactivate :一个spout可以被暂时激活和关闭,这两个方法分别在对应的时刻被调用。

nextTuple 用来发射数据。nextTuple的调用是非阻塞的。

ack(Object msgid)传入的Object其实是一个id,唯一表示一个tuple。该方法是这个id所对应的tuple被成功处理后执行。

fail(Object msgid)同ack,只不过是tuple处理失败时执行。

3.8 数据处理 Bolt 

Bolt 是接收 Spout 发出元组 Tuple 后处理数据的组件,所有的消息处理逻辑被封装在 Bolt 中,Bolt负责处理输入的数据流并产生输出的新数据流。

Bolt 可以执行过滤、函数操作、合并、写入数据库等操作。

Bolt 还可以简单地传递消息流,复杂的消息流处理往往需要很多步骤,因此也就需要很多 Bolt来处理。Bolts 也可以发射多条小溪流,使用 OutputFieldsDeclare.declareStream 定义 Stream,使用OutputCollector.emit 来选择要发射的 stream。而 Bolt 中最重要的方法是 execute(),以一个 Tuple作为输入,对 Tuple 的处理都可以放到此方法中进行。Bolt 使用 OutputCollector.emit  来发射 Tuple。

Bolt组件的实现可以通过继承BasicRichBolt类或者IRichBolt接口等来完成 
prepare方法 -- 此方法和Spout中的open方法类似,在集群中一个worker中的task初始化时调用。 它提供了bolt执行的环境 
declareOutputFields方法 -- 用于声明当前Bolt发送的Tuple中包含的字段(field),和Spout中类似 
cleanup方法 -- 同ISpout的close方法,在关闭前调用。同样不保证其一定执行。 
execute方法 -- 这是Bolt中最关键的一个方法,对于Tuple的处理都可以放到此方法中进行。具体的发送是通过
emit方法来完成的。execute接受一个 tuple进行处理,并用prepare方法传入的OutputCollector的ack方法
(表示成功)或fail(表示失败)来反馈处理结果。 

3.9 拓扑 Topology 

Storm 的 Topology 指的是类似于网络拓扑图的一种虚拟结构。Topology 类似于 MapReduce 任务,一个关键的区别是 MapReduce 任务运行一段时间后最终会完成,而 Topology 会一直运行,直到你手动kill掉。

一个Topology是Spouts和Bolts组成的有向无环图,通过流分组(StreamGroupings)将图中的Spouts和Bolts连接起来。

运行一个 Topology 很简单,首先把所有的代码以及依赖的 jar 打进一个 jar 包,然后运行类似下面这个shell命令:

Storm jar myCode.jar com.test.main.MyTopology arg1 arg2

这个命令会运行主类 com.test.main.MyTopology,参数是 arg1 跟 arg2。这个类的 main 函数定义这个Topology 并且把他提交给 Nimbus。Storm jar 负责连接 Nimbus 并且上传 jar 包。

3.10 流分组Stream Grouping 

用来定义一个流如何分配 Tuple 到 Bolt。Storm 包括 6 种流分组类型:

  • 1. 随机分组(Shuffle grouping):随机分发tuple到Bolt 的任务,保证每个任务获得相等数量的tuple。
  • 2. 字段分组(Fields grouping):根据指定字段分割数据流,并分组。例如,根据“user-id”字段,相同“user-id”的元组总是分发到同一个任务,不同“user-id”的元组可能分发到不同的任务。
  • 3. 全部分组(All grouping):tuple 被复制到 Bolt 的所有任务。这种类型需要谨慎使用。
  • 4. 全局分组(Global grouping):全部流都分配到 Bolt 的同一个任务。明确地说,是分配给 ID 最小的那个 Task。
  • 5. 无分组(None grouping):你不需要关心流是如何分组。目前,无分组等效于随机分组。但最终,Storm 将把无分组的 Bolts 放到 Bolts 或 Spouts 订阅它们的同一线程去执行(如果可能)。
  • 6. 直接分组(Direct grouping):这是一个特别的分组类型。元组生产者决定 tuple 由哪个元组处理者任务接收。
  • 7.Storm 还支持通过实现 CustomStreamGroupimg 接口来定制自己需要的分组。 

3.11 Ack机制

Storm 可以保证从 Spout 发出的每个数据都被完全处理,从 Spout 发出的数据可能会产生成千上万的数据。一个 Tuple 被完全处理指:这个 Tuple 以及这个 Tuple 产生的所有 Tuple 都被成功处理。而一个 Tuple 被认为处理失败是被是指在 timeout 时间内没有被成功处理(包括显示的fail和超时导致的失败)。这个 timeout 时间可以通过配置项 TOPOLOGY_MESSAGE_TIMEOUT_SECS来设定,Timeout 的默认时长为 30 秒。

 Storm 之所以有这样的能力是因为有个特殊的 Task 即 Acker  ,他们负责跟踪 Spout 发出的每一个 Tuple 的 Tuple 树。当 Acker 发现一个 Tuple 树已经处理完成了,它会发送一个消息给产生这个 Tuple 的那个 Task。Acker 的跟踪算法是 Storm 的主要突破之一,对任意大的一个 Tuple 树,它只需要恒定的 20 字节就可以进行跟踪。

 Acker 跟踪算法的原理: Acker 对于每个 Spout-tuple 保存一个 ack-val 的校验值,它的初始值是0,然后每发射一个 Tuple 或 Ack 一个 Tuple 时(如果成功,发射与ack总是整对出现),这个 Tuple 的 id 就要跟这个校验值异或一下,并且把得到的值更新为 ack-val 的新值。那么假设每个发射出去的 Tuple 都被 ack 了,那么最后ack-val 的值就一定是 0。Acker 就根据 ack-val 是否为 0 来判断是否完全处理,如果为 0 则认为已完全处理。 

4、storm 整体框架

 

标题

 

4.1 zookeeper中存放的数据

storm在zookeeper中存放的信息

4.1.1 worker进程的状态及统计信息

/storm/workerbeats/<topology-id>/node-port

它存储存储由node和port指定的Worker的运行状态和一些统计信息,主要包括storm-id(也即topology-id)、当前Worker 上所有Executor的统计信息(如发送的消息数目、接收的消息数目等)、当前Worker的启动时间以及最后一次更新这些信息的时间。在一个topology-id下,可能有多个node-port节点。它的内容在运行过程中会被更新。

4.1.2 Topology信息

/storm/storms/<topology-id>

存储Topology本身的信息,包括它的名字、启动时间、运行状态、要使用的Worker数以及每个组件的并行度设置。它的内容在运行过程中是不变的。

4.1.3 Supervisor上的任务信息

 /storm/assignments/<topology-id>

它存储了Nimbus为每个Topology分配的任务信息,包括该Topology在Nimbus机器本地的存储目录、被分配到的Supervisor机器到主机名的映射关系、每个Executor运行在哪个Worker上以及每个Executor的启动时间。该节点的数据在运行过程中会被更新。

4.1.4 Supervisor状态信息

/storm/supervisors/<supervisor-id>

它存储Supervisor机器本身的运行统计信息,主要包括最近一次更新时间、主机名、Supervisor-id、已经使用的端口列表、所有的端口列表以及运行时间。该节点的数据在运行过程中也会被更新。

4.1.5 错误日志

/storm/errors/<topology-id>/<component-id>/e<sequential-id>:它存储运行过程中每个组件上发生的错误信息, <sequential-id>是一个递增的序列号,每一个组件最多只会保留最近的10条错误信息,它的内容在运行过程中是不变的(但是有可能被删除)

4.2 Nimbus

Nimbus既而要在ZooKeeper中创建元数据,也要从ZooKeeper中获取元数据,下面简述箭头1和箭头2的作用

4.2.1 Nimbus创建的路径

    箭头1表示由 Nimbus创建的路径。包括:
      a. /storm/workerbeats/<topology-id>
      b. /storm/storms/<topology-id>
      c. /storm/assignments/<topology-id>

对于路径a,Nimbus只会创建路径,不会没置数据(数据是由Worker设置的,后面会介绍)。对于路径b和c, Nimbus在创建它们的时候就会设置数据,a和b只有在提交新Topology的时候才会创建,并且b的数据设置好后就不再发生变化,c则在第一次为该Topology进行任务分配的时候创建,若任务分配一划有变,Nimbus就会更新它的内容。

4.2.2 Nimbus获取数据

箭头2表示Nimbus需要获取数据的路径,包括:

      a. /storm/workerbeats/<topology-id>
      b. /storm/supervisors/<supervisor-id>
      c. /storm/errors/<topology-id>/<component-id>/e<sequential-id>

Nimbus需要从路径a读取当前已被分配的Worker的运行状态。根据该信息,Nimbus可以得知哪些Worker状态正常,哪此需要被重新调度,同时还会获取到该Worker所有Executor统计信息,这些信息会通过UI呈现给用户。从路径b 可以获取当前集群中所有Supervisor的状态;通过这些信息可以得知哪些Supervisor上还有空闲的资源可用,哪些Supervisor则已经不在活跃,需要将分配到它的任务分配到其他节点上。从路径c上可以获取当前所有的错误信息,并通过UI展现给用户。

4.3 Supervisors

    同Nimbus类似,Supervisor也要通过ZooKeeper来创建和获取元数据。Supervisor还通过监控指定的本地文件来检测由它启动的所有Worker得运行状态。

4.3.1 Supervisors启动时注册节点

箭头3 表示Supervisor 在 ZooKeeper中创建的路径是/storm/supervisors/<supervisor-id>。新节点加入时,会在该路径下创建一个节点。该节点是一个临时节点(创建ZooKeeper节点的一种模式),即只要Supervisor与ZooKeeper的连接隐定存在,该节点就一 直存在;一旦连接断开,该节点则会被自动删除。该目录下的节点列表代表了目前活跃的机器。这保证了Nimbus能及时得知当前集群中机器的状态,这是Nimbus可以进行任务 分配的基础,也是Storm具有容错性以及可扩诚性的基础。

4.3.2 Supervisors获取任务信息

箭头4表示Supervisor需要获取数据的路径是/storm/assignments/<topology-id>。我们知道它是Nimbus写入的对Topology的任务分配信息,Supervisor从该路径可以获取到Nimbus分配给它的所有任务。Supervisor在本地保存上次的分配信息,对比这两部分信息可以得知分配的任务是否有变化。若发生变化,则需要关闭被移除任务所对应的Worker,并启动新的Worker执行新分配的任务。Nimbus会尽量保持任务分配的稳定性。

4.3.3 Supervisors检查worker心跳

箭头9表示Supervisor会从LocalState 中获取它启动的所有Worker的心跳信息。Supervisor会每隔一段时间检查一次这些心跳信息,如果发现某个 Worker在这段时间内没有更新心跳信息,表明该Worker当前的运行状态出现问题。这时 Supervisor就会杀掉这个Worker,原本分配给这个Worker的任务也会被Nimbus重新分配。

4.4 worker

 Worker也需要利用ZooKeeper来创建和获取元数据,同时它还需要利用本地的文件来记录自已的心跳信息。

4.4.1 worker向zookeeper注册

箭头5表示Worker在Zookeeper中创建的路径是/storm/workerbeats/<topology-id>/node-port。nimbusWorker在Zookeeper中创建的路径是/storm/workerbeats/<topology-id>,在worker启动时,将创建一个与其对应的节点,相当于对自身进行注册。避免多个Worker同时创建路径时导致冲突。

4.4.2 worker拉取任务信息并执行

箭头6表示worker从/storm/assignments/<topology-id>的任务分配信息中取出分配给她的任务并执行。

4.4.3 worker与supervisor通过本地文件传递心跳

箭头8表示worker在LocalState(本地文件)中保存心跳信息。worker通过这些信息与Supervisor保持心跳,每隔几秒更新一次心跳信息。worker和supervisor是不同的进程,storm采用本地文件方式传递心跳信息。

4.5 Excutor

excutor只利用zookeeper存放运行错误信息。箭头7表示

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值