Storm Tutorial
笔者三级英语水平,还请见谅!!!
学习创建Storm topologies并部署到一个Strom集群上。
组件
一个Strom的集群看起来非常像Hadoop集群。Hadoop集群上跑的是”MapReduce jobs”,Strom上跑的是”topologies jobs”,其中最主要的区别是,MapReduce jobs会终止,topologies不会停止除非被kill。
这里有两种节点运行字集群上:master和worker。Master节点运行在一个名叫”Nimbus”的后台进程类似Hadoop的”JobTracker”.Nimbus负责分配代码到集群、分派任务给工作机、监控异常。
每一个worker运行在叫”Supervisor”的后后台进程。Supervisor监听Nimbus分配的任务,启动和停止相关的worker的线程。每个worker线程执行拓扑的的子集;一个拓扑图包含了很多个worker分布在不同的机器上。
如图所示,所有的Nimbud和Supervisor的协调是通过Zookeeper实现的。此外Nimbus和Supervisor进程是fail-fast、武装态度的,所有的状态保存在Zookeeper和本地的磁盘上。这就意味着用kill -9杀死这些进程后,他们会很快被重新启动,就像什么都没有发生一样。
拓扑结构
为了Storm实时计算,必须创建拓扑结构。拓扑结构是一个有向无环图,拓扑图上的每个节点,每个节点由运算逻辑和决定怎么传输数据到周围节点的链接组成。
运行一个拓扑结非常简单:1.打包所有的依赖包和代码;2.运行下列命令。
storm jar all-my-code.jar backtype.storm.MyTopology arg1 arg2
在backtype.storm.MyTopology类中的主方法被提交到Nimbus;
Streams
Storm核心的得抽象类”Stream”.stream是一个无界元祖的序列。Storm提供支持,用于将一个流转化成一个分布式和可靠流。
Storm用于转化stream的基本单元是”spouts”和”bolts”.Spouts和Bolts提供接口用来实现自己的逻辑。
Spout是流的源。一个spou从队列t读取元组并且以流的方式发送(输出)。或者一个spout从Twitter API发送(输出)Twitter的数据流。
Bolt消费一些输入的流,做些许的运算或是发送(输出)新的流。综合stream转化,像是完成将鸟叫声转化成流行主题的流,需要多个bolt多步处理。从简单功能、过滤元组、流的聚合、访问数据库等Bolts可以做任何操作。
网络中的bolts和spouts被封装在”topology”中,一个最高层次的抽象类,用于提交到Storm集群执行。一个”topology”是一个有向无环图,节点是一个spout或是bolt。这个图的边缘显示那些bolt订阅了那个流。当一个spout或是bolt发送一个元组到六中,他会发送这些元组到每个订阅这个流的bolt。
将节点连接起来,指出元组通过的路径。拓扑结构中的每个节点都是可执行的。在拓扑结构图中可以指定如何对应每个节点,然后storm会自动触发一些线程通过集群去执行。一个拓扑结构会永远运行,storm会重新分配线程为失败的任务。
数据类型
Storm使用元组作为基本数据模型。一个元组是一个命名的值的集合,在元组的作用域中可以是Object型和任何的数据类型。内存不足时,Storm支持所有的基础数据类型,strings、元组值的字节数组。自定义的数据类型需要实现可序列化的接口。
每一个拓扑结构中的节点需要为发送的元组声明输出域(指定元组输出的节点)。举个栗子,这个bolt声明的他的元组的两个发送目标是”double”,”triple”.
public class DoubleAndTripleBolt extends BaseRichBolt {
private OutputCollectorBase _collector;
@Override
public void prepare(Map conf, TopologyContext context, OutputCollectorBase collector) {
_collector = collector;
}
@Override
public void execute(Tuple input) {
int val = input.getInteger(0);
_collector.emit(input, new Values(val*2, val*3));
_collector.ack(input);
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("double", "triple"));
}
}
declareOutputFields方法声明了bolt发送元组的域。
一个简单的拓扑
根据一个简单的拓扑结构探索怎么样创建代码。from-starter定义一个拓扑结构:
TopologyBuilder builder = new TopologyBuilder(); builder.setSpout("words", new TestWordSpout(), 10);
builder.setBolt("exclaim1", new ExclamationBolt(), 3)
.shuffleGrouping("words");
builder.setBolt("exclaim2", new ExclamationBolt(), 2)
.shuffleGrouping("exclaim1");
下班后再更新。。。