Storm学习笔记

2017/12/03

对Storm的一些学习记录


Storm的数据模型

  • Tuple Tuple是整个Storm数据模型最小颗粒度的单元,它代表的是被一次处理的一个数据集
  • Stream 就是具有相同数据结构(或被人为该类成一类数据)的Tuple的集合,其实就是把Tuple分类了,一个Stream就是一个种类的Tuple.(先看完下面,再看这个例子:一个Spout可以生成多个Steam,也就是Spout把元数据,分类包装成了多种数据结构不同的Tuple,他们就属于不同的Stream,然后下游的Bolt就可以通过Stream ID来指定关注不同的Stream,从而只能读入指定一类(数据结构)的Tuple)
  • Spout 是一个Topology的起点,它负责读入外部数据,然后包装成Tuple再emit(喷出去,Storm术语),从而让其他Bolt(下面有介绍)可以接受Tuple并做出接下来的处理
  • Bolt 是Topology处理业务逻辑的地方,同时它也可以它可以把读进来的Tuple进行转换,加工,然后再emit出去,供下游的其他Bolts进行逻辑处理
  • Tuple ID 每个Tuple都有一个ID,这个ID可以是任何类型,只要可以唯一识别出这个Tuple,Spout在生成Tuple的时候就会生成这个ID,之后一切由这个Tuple衍生出来的Tuple都会带上ID(生成了一个Tuple ID 对应的Tuple树).Tuple在整个Topology执行完成,或者在未执行完成就失败了(整个Tuple树,只要有任何一个节点失败了,都算失败)的时候会得到Storm的(acker调度器)调度通知,通知Spout调用ack或者fail方法,处理对应ID的Tuple.
  • Stream ID 每个Spout和Bolt都可以产生多个Stream,Bolt也可以同时订阅多个Stream,所以每个Stream都会有个Steam ID,默认的Stream ID 就是 “default”
  • Topology 简答来说就是一个完整的业务逻辑图,由多个Spout和Bolt组成

Storm整个分布式结构

  • Storm是重度依赖Zookeeper集群的
  • Storm是master-slave结构
  • Nimbus 是Master它的作用是部署应用代码(就是topology)到字节点,分发任务到子节点,以及监控,调度分发的任务(包括失败重试)
  • Supervisor 是子节点,每个子节点都会运行一个supervisor daemon来监控和调度worker进程(就是每个子节点下面有很多个worker进程,worker进程才是真正执行topology逻辑的)
  • Nimbus和Supervisor都是状态无关的,它们的所有状态信息都存储在zookeeper,而且它们不会互相之间不会直接交互,它们都是通过zookeeper来实现彼此之间的交互动作,所以它们可以快速失败,任何一个节点的失败重启之类的操作都不会 影响它们已经提交的任务
  • Woeker ,一个worker只能属于一个topology,运行一整个topology或者是一个topology的某部分
  • Executor ,每个worker是多线程运行的,每个Executor其实就是一条线程,每个Executor只会运行一个spout或者一个bolt,分配给每个spout或者bolt的线程数是可以在topology的运行时进行修改的
  • Task , Task 是Storm的最小的执行单元,每个Task其实就是一个spout或者bolt的 实例,默认情况下,每个Executor只有一个Task. Task的数量是可以被指定的,Task的数量一定>=Executor的数量,Task会被平均分配到每个Executor上,当多个Task分配到一个Executor上的时候,所有的Task都是串行的.由于每个Executor只会运行一个spout或者一个bolt,那换句话说每个Executor只会运行属于某个spout或者某个bolt的Tasks
  • parallelism hint storm术语,指的是每个组件(spout或者bolt)的Executor数量(注意,默认情况下,每个Executor只有一个Task)
  • Task的数量一定>=Executor的数量的原因 1.Task的数量是在topology的运行时无法改变的,supervisor,worker和Executor的数量是可以在运行时改变的,这时候,当你一开始设置的每个Executor都执行大于1个Task,当添加了新的Executor再进行rebalance的时候,就可以做到每个Executor执行一个Task,从而达到整个拓扑的横向扩展. 2.假设你的测试环境的硬件数量要比你的生产环境的硬件数量少,这时候你优先分配多个Task在一个Executor上,可以可变验证该配置的正确性,从而避免上生产环境的时候出现更多的不可预测的因素.

总结

良好的设计是,一个Bolt只做单一的逻辑,把复杂的逻辑拆成多个Bolt逐一完成,这样做既可以方便扩展,也可以把设计解耦,也可以方便排错,维护等…诸多好处