Strom完整攻略(一)

前言

Strom特点
进程常驻内存,数据不经过磁盘,在内存中处理,速度非常快,可以达到毫秒(秒)级别

Storm数据传输
采用Netty,基于NIO,更加高效,早期采用ZMQ,但是ZMQ和Strom的license不兼容。

Storm可靠性

  • 异常处理
  • 消息可靠性的保证机制ACK

Strom和其他框架的对比
1.Spark-Streaming 微批处理框架 秒级,不是纯流式计算框架和Spark核心之上的计算模型,和Spark的其他组件兼容较好。
2.MR 批处理框架,分钟级别,MR模型,反复启停。
3.Strom 秒(毫秒)级别,流式处理,DAG模型有向无环图,常驻运行,不关闭,独立系统专为流式处理设计。

一.Storm编程模型

  • Spout:用于持续不断的发送数据

  • Tuple:数据都被封装进tuple容器,进行传输,Storm中发送数据的基本单元,Tuple不断的向后传输,像水滴一样

  • Bolt:用于接受并处理数据

  • Stream:从Spout中源源不断传递数据给Blot,以及上一个Blog传递数据给下一个Blot,所组成的数据通道叫做Stream,Stream默认的名称为default,可以为其指定id。

  • 并行度:可以使用多线程模型,充分利用CPU,可以有效应对高并发,高数据量的应用场景,还可以多台服务器,多节点,多线程运行任务

  • 有向无环图(Directed Acyclic Graph):对于Storm实时计算逻辑的封装,即通过一系列由数据流相互关联的Spout、Blot所组成的拓扑结构

二.Storm的分发策略

1、Shuffle Grouping
随机分发,随机派发Stream里面的tuple,保证每个bolt task接收到的tuple的数量大致相同

2、Field Grouping
根据字段分发,例如根据OutputFieldsDeclarer中声明的一个field属性进行分发,field的对应的tuple的值相同,就会分发到同一bolt中去进行处理,filed不同可能就会被分发到不同的task

3、All Grouping
广播模式分发,每一个tuple都会被分发到下一个阶段的所有的bolt中

4、Global Grouping分发
将tuple分发到后续bolt中taskid最小的task中去执行,可以看做是高可用,其他的bolt作为备用,一旦taskid最小的task对应的bolt挂了,还有bolt可以使用,可以保证Storm集群的可用性

5、None Grouping
类似于Shuffle Grouping,不同的是None Grouping采用的是轮训的形式,Shuffle采用的是随机分发有一点不同的是storm会把使用none grouping的这个bolt放到这个bolt的订阅者同一个线程里面去执行

6、Direct Grouping
指向性分发,这种分发策略意味着消息(tuple)的发送者指定由消息接受者的哪个task来处理消息,只有被声明为Direct Stream的消息流可以声明这种分组方法,而且这种消息必须由emitDirect方法来发送。可以使用TopologyContext获取taskId,还有outputCollector.emit()方法也可以返回taskid

7、Local or Shuffle Grouping
本地随机分组,如果目标bolt有一个或者多个task与源bolt的task在同进程中,则随机分发到同进程的task中,否则和Shuffle Grouping一样

8、自定义分发 customGrouping

三.Storm 架构模型

1.Nimbus 主节点的守护进程

  • 负责资源调度
  • 任务分配
  • 接受Client上传的jar包

2.Supervisor 从节点的守护进程,具体完成计算工作
接受NimBus分配的任务->监视ZK节点看是否有分配给自己的任务

启动、关闭自己管理的Worker进程,可以有多个Worker进程,Work进程的数量由配置文件设定,配置文件是Client上传jar包的配置文件,即由Client指定。

3.Worker 从节点的工作进程
由Supervisor控制启动关闭,专门用于计算,所有的拓扑作业在Worker上运行。

运行具体运算组件的进程,一个topology可能会在一个或者多个worker(工作进程)里面执行。

Worker任务的类型只有两种, Spout和Bolt。

Executor是Worker JVM内部的一个线程,一般每个Executor负责运行一个或多个任务,但仅用于特定的spout或bolt。但一般默认
每个executor只执行一个task。

Worker中可以启动多个线程Executor,执行特定的spout对应的多个task任务,提高并行度,但是注意每个task的taskid不一致,taskid起到了区分作用。

4.Zookeeper
替代了部分Nimbus的作用,也是目前storm是不支持nimbus高可用的但能保证系统不受太大影响的一个支撑。

Zookeeper本身已经是按至少三台部署的HA架构了。Supervisor进程和Nimbus进程,需要用Daemon程序如monit来启动,失效时自动重新启动。因为它们在进程内都不保存状态,状态都保存在本地文件和ZooKeeper,因此进程可以随便杀。

如果Nimbus进程所在的机器都直接倒了,需要在其他机器上重新启动,Storm目前没有自建支持,需要自己写脚本实现。即使Nimbus进程不在了,也只是不能部署新任务,有节点失效时不能重新分配而已,不影响已有的线程。同样,如果Supervisor进程失效,不影响已存在的Worker进程。

目前storm官方或许是出于nimbus宕机对集群影响不大的考虑,并没有在这方面有所进展。

四.Strom 任务提交流程

image.png

1.Client提交topology作业的相关jar包到Nimbus

2.提交的jar包会被上传到Nimbus服务器下的Store-local/nimbus/inbox目录下

3.submitTopology方法负责对这个topology进行处理。

  • 首先对storm本身和topology进行一些校验,检查storm状态是否是active的
  • 检查是否存在同名的topology已经在storm中运行了
  • 检查topology中的spout和bolt是否使用了相同的id,以及id是否规范,不能以开头,是系统保留的命名方式

4.建立topology的本地文件目录 /nimbus/stormdist/topology-uuid

该目录包括三个文件

  • stormjar.jar :包含这个topology的所有代码的jar包
  • stomecode.ser --这个topology对象的序列化
  • stomeconf.ser --运行这个topology的配置

5.numbus分配任务,获取空闲的work,根据topology定义中给的numworker参数、parallelism参数和numTask数量,给spout和bolt设置task数目,并且分配相应的task-id,分配worker

6.numbus在ZK上创建taskbeat目录,要求每个task每隔一定时间就要发送心跳汇报状态

7.将分配好的任务写入到zk中,此刻任务才算提交完毕,zk上节点为assignment/topology-uuid

8.将topology的信息写入到zookeeper/storms目录

9.Supervisor监听zookeeper上的storms目录,看看是否有所属的新的任务,有就根据任务信息,启动worker,下载下来jar包

10.删除本地不再运行的topology代码

11.supervisor根据nimbus指定的任务信息启动worker进行工作

12.work根据taskid分辨出spout和blot

13.计算出所代表的spout/blot会给哪些task发送消息

14.根据ip和端口号创建响应的网络连接用来发送消息

Storm本地目录树

Storm本地目录树

Zookeeper目录树

Zookeeper目录树

Storm程序的并发机制

并发机制

从官网的解释中,我们可以得出以下几点。

1.Workers (JVMs):

  • 一个Topology拓扑可以在一个或多个Worker上运行,(每个Worker进程只能从属于一个特定的Topology)
  • 这些Worker进程会并行跑在集群中不同的服务器上,即一个Topology拓扑其实是由并行运行在Storm集群中多台服务器上的进程所组成。

2.Executors (threads):

  • Executor是由Worker进程中生成的一个线程
  • 每个Worker进程中会运行拓扑中的一个或多个Executor线程。
  • 一个Executor线程线程可以执行一个或者多个Task任务,默认只运行一个任务,但是这些任务都对应相同的Component(Spout/Blot)。

3.Tasks(bolt/spout instances):

  • 实际执行数据处理的最小单元
  • 每个task即为一个Spout或者一个Bolt。
  • Task数量在整个Topology生命周期中保持不变,worker,Executor数量可以变化或手动调整。
  • 默认情况下,Task数量和Executor是相同的,即每个Executor线程中默认运行一个Task任务
  • 可以调用TopologyBuilder.setSpout和TopBuilder.setBolt来设置并行度,也就是有多少个task。

4.对应关系总结
Topology与Woker的关系

  • 1:n
  • 1:1

Executor与Task的关系

  • 1:1
  • 1:n(相同的Component)

image.png

对应上图的代码示例

Config conf = newConfig();
//用2个worker
conf.setNumWorkers(2); 
//设置2个并发度
topologyBuilder.setSpout("blue-spout", newBlueSpout(), 2); 
////设置2个并发度,4个任务
topologyBuilder.setBolt("green-bolt", newGreenBolt(), 2).setNumTasks(4).shuffleGrouping("blue-spout"); 
 //设置6个并发度
topologyBuilder.setBolt("yellow-bolt", newYellowBolt(), 6).shuffleGrouping("green-bolt");
StormSubmitter.submitTopology("mytopology", conf, topologyBuilder.createTopology());

由上可知,3个组件的并发度加起来是10,就是说拓扑一共有10个executor,一共有2个worker,每个worker产生10 / 2 = 5条线程。

绿色的bolt配置成2个executor和4个task。为此每个executor为这个bolt运行2个task。黄色bolt和蓝色的spout都是一个executor运行一个task。

对于并发度的配置, 在storm里面可以在多个地方进行配置, 优先级为:
defaults.yaml < storm.yaml < topology-specific configuration < internal component-specific configuration < external component-specific configuration

Storm的Rebalance – 再平衡

动态调整Topology拓扑的Worker进程数量、以及Executor线程数量。支持两种调整方式:

1、通过Storm UI

2、通过Storm CLI
storm rebalance mytopology -n 5 -e blue-spout=3 -e yellow-bolt=10
将mytopology拓扑worker进程数量调整为5个,“ blue-spout ” 所使用的线程数量调整为3个,“ yellow-bolt ”所使用的线程数量调整为10个。

你可能感兴趣的:(Strom完整攻略(一))