一、Components of a Storm cluster
1)机器级别的结构:one master node,many worker nodes,ZooKeeper nodes
2)进程级别的结构:one daemon called Nimbus run on the master node,one daemon called Supervisor run on each of the worker nodes,ZooKeeper daemon run on each of the ZooKeeper nodes
the Supervisor can start many processes as necessary based on what Nimbus has assigned to it
3)作业称呼:topology[whereas on Hadoop,it is called MapReduce Job]
二、Usage
1)用户定义一个topology实例,提交给在master node上的Nimbus,然后Nimbus会进行接管,它会通过Supervisor将必需的代码复制到所在的worker node,也会进行任务调度等工作
三、Topology介绍
1)Topology是具有图形状的计算结构,它包含有两种节点,分别是Spout和Bolt,数据在Topology中以流的形式存在
2)Spout节点是流的源头,它接受数据,经过处理后以流的形式输出
3)Bolt节点是流的处理节点,它接受流数据,经过处理,输出流数据
4)Spout和Bolt节点的输出节点都只能是Bolt节点
5)Spout的输入节点是原始数据源,Bolt的输入节点可以是Spout节点,也可以是Bolt节点
6)Topology中节点之间传输数据的唯一途径是通过流通道,每条流通道都有一个ID,如果不指定该ID,表示默认流通道,节点之间可以建立多条流通道,而不像图中所示仅仅只有一条
四、关于Topology中的进程(Process),线程(Thread),任务(Task)
1)在配置Topology的时候,可以设定整个Topology的进程数量,比如如下:
Config conf=new Config();
conf.setNumWorkers(2);
就是设置整个Topology的进程总数为2个,具体在哪些Worker Nodes上创建进程,由Nimbus调度,具体由Supervisor创建
2)最终任务是通过进程中的线程运行的,注意线程是在进程中运行的
在设置Spout和Bolt的时候,可以指定Spout节点和Bolt节点所需要的线程数,比如
TopologyBuilder builder=new TopologyBuilder();
builder.setSpout(“words”,new TestWordSpout(),10);
builder.setBolt(“exclaim”,new ExclamationBolt(),4);
这些线程还是在前面提到的进程中运行的
如果通过第1步设定了7个进程,这里所有节点加起来需要14个线程,那么每个进程中运行2个线程
3)任务表示一个节点中真正的处理逻辑,一个线程中可以运行1个到多个任务,每个节点的任务数可以人工指定
ComponentConfigurationDeclarer.setNumTasks();
五、流通道和流分组
流通道如上面所述是节点之间传输数据的唯一途径,流分组的概念与流通道的概念互相独立
在A节点(源节点)和B节点(目的节点)之间建立一条流通道之后,A中的流数据会传递到B中,而如上所述,每个节点中有多个任务,如何将得到的流数据分配到各个任务中,就是流分组问题
常见的流分组方式有
1、shuffleGrouping
随机地将得到的数据分配给多个任务
2、fieldsGrouping
根据字段值进行划分[具体是hash方式,模值是任务总数,那么就能够保证同值的数据被分配到同一个任务上,但是不能保证同一个任务上只有同值的数据],将得到的数据分配给任务
比如数据值为整数,而现在有两个任务,那么一个任务就接受奇数,另外一个任务就接受偶数就好了
六、编程流程
针对Topology的编程,其实主要是配置实现Spout和Bolt节点的逻辑,主要有3个方面:分别是配置节点的流输入和流输出,配置节点的流输入格式和流输出格式,实现节点的处理逻辑。
1)配置节点的流输入和流输出
配置了某个节点的流输入,其实就同时配置好了另外某个节点的流输出,因而我们只要配置流输入就可以。
流的输入和输出的关系因具体的流通道的建立而建立,因此配置流的输入和输出关系必须指定具体的流通道ID,如果不指定,则采用默认的流通道ID。[1]
InputDeclarer接口下的shuffleGrouping()和fieldsGrouping()接口都是用来设置流输入关系的,比如
//”sentences” is the spout instance id
builder.setBolt("split", new SplitSentence(), 8)
.shuffleGrouping("sentences");
//”split” is the bolt instance id
builder.setBolt("count", new WordCount(), 12)
.fieldsGrouping("split", new Fields("word"));
2)配置节点的流输入格式和流输出格式
配置了某个节点的流输出格式,其实也就配置了另外某个节点的流输入格式,因而只需配置节点的流输出格式就可以。
在Spout和Bolt实现中的declareOutputFields()接口就用来做这件事
3)实现节点的处理逻辑
在Spout实现中的nextTuple()接口和在Bolt实现中的execute()接口就用来做这件事
七、编程过程简化
你定义好一个Topology实例,配置好Spout节点和Bolt节点,并且定义好它们之间的数据连接关系,然后将该实例提交给Nimbus,它会管控好接下来的细节。
从外部来看,整个Storm集群的表现行为就像一台主机,只要我们定义好Topology实例提交给它,它就会读取输入数据,然后依次经过Spout节点,Bolt节点,最后将结果输出。
这个逻辑抽象,非常有利于简化我们的编程过程。
这里的“外部”是指调用Nimbus服务的外部应用程序,一般与Nimbus服务处于同一台机子,即master node,也可以处于非master node上,通过远程调用的形式来调用master node上的Nimbus服务
这个外部应用不只可以调用Nimbus服务,也可以调用本机(master node)的本地服务,比如本机磁盘存取服务
下图阐述了上述关系
来源:https://storm.apache.org/documentation/Tutorial.html
参考文献:
[1]https://storm.apache.org/documentation/Concepts.html
[2]http://www.michael-noll.com/blog/2012/10/16/understanding-the-parallelism-of-a-storm-topology/
[3]http://docs.hortonworks.com/HDPDocuments/HDP2/HDP-2.1.2/bk_user-guide/content/ch_storm-using-basic-concepts.html
[4]http://book.51cto.com/art/201410/453385.htm
[5]http://ifeve.com/getting-started-with-storm6/