一 什么是拓扑
Storm中的拓扑,实际上就是一个有向图的计算。拓扑中节点包含数据的逻辑处理;节点之间的边显示数据如何在节点直接流动。
二 Java中如何建立拓扑
1 首先创建一个TopologyBuilder对象。
2 使用setSpout方法和setBolt方法,建立拓扑中的节点以及节点之间的联系。(方法的参数列表:第一个参数表示组件的id;第二个参数是Spout或者Bolt对象,包含数据的处理逻辑;第三个参数表示组件的并行度,也就是执行器(或线程)的数量,默认为1)。
如果要用一个Bolt订阅多个数据来源,在Bolt内部可以调用Tuple的getSourceComponent方法确定tuple来自哪个组件。
3 对拓扑中的参数进行配置(可以使用HashMap对象或者Storm中的backtype.storm.Config对象)。
4 使用TopologyBuilder对象创建拓扑,并提交拓扑。(可以选择提交到生产环境的Storm集群;或者开发调试环境的LocalCluster)。
三 流分组
流分组定义了元组(tuple)如何在组件(Spout和Bolt)之间分发。
Storm内置了7中流分组方式,此外,开发者还可以通过实现CustomStreamGrouping接口,开发自己的分组方式。
1 随机分组(shuffle grouping)
最常用的分组方式,它随机的将元组分发到Bolt的任务上,这样可以保证每个任务得到数量相同的元组,提高并发能力。
2 字段分组(Field grouping)
根据指定的字段对流进行分组。具有相同字段值的tuple将会被分配到同一个任务中。
在实现上,是通过Hash取模来实现的。
3 广播分组(All grouping)
流被发送到所有的Bolt任务中,任意一个Bolt中的tuple处理失败,将会引起spout元组处理失败。
4 全局分组(Global grouping)
全部流都将转发到Bolt的同一任务中。(ID最小的任务)
5 无分组
这种分组方式的效果和随机分组相同,不同的是,Storm会将这个Bolt放到其订阅的Bolt的线程中执行。(两个Bolt共享了一个线程)
6 直接分组(Direct grouping)
这是一种特殊的分组方式,由元组的生产者决定将元组发送到消费者的那个任务。
直接分组只能在已经声明为直接流的数据流中使用,并且必须使用emitDirect方法来发送。
7 本地或者随机分组
如果元组生产者和目标Bolt在同一个工作进程(Worker)存在一个或多个任务,元组将会被随机分配给这些任务;否则效果和随机分组相同。
8 自定义分组
实现CustomStreamGrouping接口。
四 本地模式和分布式模式
1 本地模式
(1)本地模式是在开发环境中,Storm模拟工作节点的线程在进程中执行。这种模式对于Storm程序的开发和测试是很有用的。
(2)常用配置
TOPOLOGY_WORKERS:分配多少进程到集群中去执行拓扑。
TOPOLOGY_DEBUG:当配置为true时,每一个组件发射每一个消息都会被Storm记录到日志中。
2 分布式模式
(1)分布式模式就是真实的生产环境,Storm被部署在服务器集群中,Storm程序需要提交到主控节点上被执行。
(2)常用配置
TOPOLOGY_WORKERS:工作进程数量
TOPOLOGY_ACKERS:跟踪元组树的任务数量
TOPOLOGY_MAX_SPOUT_PENDING:设置一次可以在Spout任务中等待的元组数量,当上一个元组没有ack或者fail时,后面的元组需要等待。这个配置可以防止队列溢出。
TOPOLOGY_MESSAGE_TIMEOUT_SECS:等待一个元组完成还是失败的最大时间,默认30秒。
TOPOLOGY_SERIALIZATIONS:注册序列化器,从而在元组中使用自定义类型。
五 常见的拓扑模式
1 流连接(Stream join)
基于一些常用的字段(字段分组),将多个流结合在一起,形成一个新的数据流
2 批处理(Batching)
在Bolt中,使用一个实例变量保存一组元组的引用,对这组元组做完批处理之后,再ack所有保存的元组。
3 BasicBolt
常见的实现可靠性的模式,是在Bolt中获取、处理元组,之后发射新的元组,并锚定输入元组。在execute方法最后,ack输入元组。
Storm提供了IBasicBolt接口,可以自动实现以上机制,Bolt只需要发射新的元组即可,锚定和ack的动作自动完成。
4 内存中缓存与字段的组合
在Bolt中存储缓存是一种常见的用法,如果缓存和字段分组相配合,将具有相同字段的tuple发送到同一个任务中,将有效提高缓存的命中率。
5 流的top N
使用多个Bolt任务并行的进行top N计算(字段分组),之后使用全局分组,将所有的Bolt任务计算结果,合并到一个Bolt中。这样充分利用了集群并行计算的能力,最终还得到了合并后的结果。
6 分布式RPC
Spout从RPC服务器中获取到函数名和参数,之后使用Bolt进行计算,最后的Bolt将结果发送到RPC服务器中,实现分布式RPC。