对于大数据技术进行了一阶段的学习,我从个人的理解角度来对storm做出一定的分析
一、storm的原理进行分析
1、storm适用的场景
A> 流数据的处理---storm可以用来处理源源不断的消息,并将处理后的结果保存到持久化的介质中(持久化的介质可指:MySql、Orcal)
B>分布式的RPC---由于storm的处理组件都是分布式的,而且处理延迟都极低,所以storm可以作为一个通用的分布式PRC框架来使用
2、storm分析(从与hadoop对比的角度)
hadoop | storm |
MapReduce分布式计算框架 | Twitter主持的分布式计算系统 |
离线的、复杂的大数据 | 在线的、实时的大数据处理 |
二、一个storm集群的基本组件
A>storm上面运行的是Topology,一个Topology永远会运行(除非显式的杀掉他)
B>Storm的集群里面有两个节点:1.master node(控制节点) 2.work node(工作节点)
C>Storm组件以及任务:
Storm组件示意图
D>Storm Topology结构
1.系统角色:Nimbus、Supervisor、Worker
2.应用名称:Topology
3.组件接口:Spout/Bolt
F>Topology
为了在storm上面做实时计算,需要建立一些topologies。一个topology就是一个计算节点所组成的图。Topology里面的每个处理节点都包含处理逻辑,而节点之间的连接则表示数据流动的方向。Topology的定义其实就是一个Thrift结构并且nimbus就是一个Thrift服务,可以用任何语言创建并且提交Topology。Spout和Bolt所组成一个网络会被打成Topology,Topology是Strom里面最高一级的抽象(类似hadoop中的job)。Topology里面的每一个节点都是并行运行的,但是在自己的topology中,可以指定每个节点的并行度,Storm则会在集群里面分配那么多线程来同时计算。一个Topology会一直运行直到你显式停止它,storm自动重新分配一些运行失败的任务,并且Storm保证你不会有数据丢失,即使一些机器意外停止并且消息被丢掉的情况下。
G>Stream、Spout、和Bolt
Stream是storm里面的关键抽象,一个Storm是一个没有边界的tuple序列,Storm提供一些原语来分布式、可靠地把一个Stream传输进一个新的Stream。Storm提供的最基本的处理Stream的原语是spout和bolt,通过实现Spout和Bolt对应得接口以处理你的应用的逻辑。Spout的流的源头,通常Spout会从外部数据源(队列、数据库等)读取数据,然后封装更Tuple形式,之后发到Stream中。Spout是一个主动地角色,在接口内部有个nextTouple函数,Storm框架会不停的调用该函数;
Bolt可以接收任意多个输入Stream,作一些处理,有些blot可能会发射一些新的Stream,bolt可以做任何事情:运行函数,过滤tuple,做一些聚合,做一些合并以及访问数据库等。Bolt处理输入的Stream,并产生新的输出Stream。Bolt可以执行过滤、函数操作、join、操作数据库等任何操作。Bolt是一个被动的角色,其接口有一个execute(T丿;le input)方法,在接收到消息之后会调用此函数,用户可以在此方法中执行自己的处理逻辑。
三、数据模型(Data Model)
Storm使用tuple来作为它的数据模型,每个tuple是一堆值,每个值有一个名字,并且每个值可以是任何类型(可以将一个tuple作为一个没有方法的Java对象),总体来看,Storm支持所有的基本类型、字符串以及字节数组作为tuple的值类型,你也可以使用你自己定义的类型来作为值类型,只要你实现对应的序列化器(serializer)。
一个tuple代表数据流中的一个基本的处理单元,例如:一条cookie日志,它可以包含多个Field,每一个Field表示一个属性。
Tuple本来是一个Key-Value的Map,由于各个组件间传递的tuple的字段名称已经事先定义好了,所以Tuple只需要按序填入各个Value,所以就是一个Value List。
一个没有边界、源源不断的、连续的Tuple序列就组成了Stream
Topology里面的每个节点必须定义它要发射的tuple的每个字段,如下的bolt定义它所发射的tuple包含的两个字段,类型分别是double和triple。
public class DoubleAndTripleBolt implements IRichBolt {
private OutputCollectorBase_collector;
@Override
public void prepare(Map conf,TopologyContext Context,OutputCollectorBase collector)
{
_collector=collector;
}
@Override
public void dexecute(Tuple input)
{
intval=input.getInteger(0);
_collector.emit(input,newValue)(val*2,val*3);
_collector.ack(input);
}
@Override
public void cleanup()
{
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer)
{
declare.declare(newFields("double","triple"))
}
declareOutputFields方法定义要输出的字段:【"double","triple"】。
Storm的运行有两种模式:本地模式和分布式模式。当你提交topology给master的时候,你同时也将topology的代码提交了,master负责分发你的代码并且负责给你的topology分配工作进程。如果一个工作的进程挂掉了,master几点会把认为重新分配到其它节点。
关于如何在集群上面运行topology,可以参考Running topologies on a production cluster。
如下是以本地模式运行ExclamationTopology的代码:
Config conf=new Config();
conf.setDebug(true);
conf.setNumWorker(2);
LocalCluster cluster=new LocalCluster();
cluster.sumbitTopology("test",conf,builder.createTopology());
Utils.sleep(10000);
cluster.killTopology("test");
cluster.shutdown();
首先,定义一个LocalCluster对象来定义一个进程内的集群,提交topology给这个虚拟的集群和提交topology给分布式是一样的,通过调用sumbitTopology方法来提交topology,它接受3个参数:要运行的topology的名字、一个配置对象以及要运行的topology本身。
Topology的名字是用来唯一区别一个topology的,这样可以用这个名字来杀死这个topology;
Conf对象是可以配置很多东西的,以下两个最为常见:
TOPOLOGY_WORKERS(setNumWorkers)定义你希望集群分配多少个工作进程来给你执行这个topology,topology里面的每个组件会被需要线程来执行,每个组件到底用多少个线程是通过setBolt和setSpout来指定的,这些线程都运行在工作进程里面,每一个工作进程包含一些节点的一些工作线程。
TOPOLOGY_DEBUG(setDebug),当它被设置成true的话,storm会记录下每个组件所发射的每条消息,这在本地环境调试topology很有用,但是在线上这么做的话会很影响性能。
运行中的Topology主要由以下三个组件组成的:
1.Worker processes(进程)
2.Executors (threads)(线程)
3.Tasks