分组策略和并发度
一、Stream Grouping
所谓的分组策略就是在Spout与Bolt、Bolt与Bolt之间传递Tuple的方式。 stream grouping用来定义一个stream应该如何分配给Bolts上面的多个Executors(多线程、多并发)。
Stream grouping的类型
Storm里面有7种
1)Shuffle Grouping: 随机分组,轮询,平均分配。随机派发stream里面的tuple,保证每个bolt接收到的tuple数目大致相同。
2)Fields Grouping:按字段分组,比如按userid来分组,具有同样userid的tuple会被分到相同的Bolts里的一个task,而不同的userid则会被分配到不同的bolts里的task。
3)All Grouping:广播发送,对于每一个tuple,所有的bolts都会收到。
4)Global Grouping:全局分组,这个tuple被分配到storm中的一个bolt的其中一个task。再具体一点就是分配给id值最低的那个task。
5)Non Grouping:不分组,这stream grouping个分组的意思是说stream不关心到底谁会收到它的tuple。目前这种分组和Shuffle grouping是一样的效果。在多线程情况下不平均分配。
6)Direct Grouping:直接分组,这是一种比较特别的分组方法,用这种分组意味着消息的发送者指定由消息接收者的哪个task处理这个消息。只有被声明为Direct Stream的消息流可以声明这种分组方法。而且这种消息tuple必须使用emitDirect方法来发射。消息处理者可以通过TopologyContext来获取处理它的消息的task的id (OutputCollector.emit方法也会返回task的id)。
7)Local or shuffle grouping:如果目标bolt有一个或者多个task在同一个工作进程中,tuple将会被随机发送给这些tasks。否则,和普通的Shuffle Grouping行为一致。
二、并发度
1.概念回顾:
一般对于物理节点来讲,我们部署的节点的类型包括nimbus(master),supervisor(slave),通常是一个nimbus,多个supervisor。nimbus是负责安排任务给supervisor去完成的,即supervisor是实际上干活的。
而对于一个supervisor来讲,它可以包含多个worker,worker有可以包含多个executor,executor又可以执行多个task。
supervisor和node是一一对应的关系,而worker就是process(进程),executor就是thread(线程),task就是在spout或bolt中定义的函数。
那supervisor,worker和executor跟topology或component(包括spout和bolt)之间的对应关系呢?
-
一个topology可以在多个supervisor上执行,一个supervisor也可以执行多个topology
-
但是,一个worker只执行某个topology,一个topology由多个worker来执行
-
一个executor可以执行一个component中的多个task,但是一个component可以由多个executor来执行,这就是我们在编程中指定的并发程度。后面会看到。
-
一个executor默认对应一个task
-
一个worker中包含多个executor,但是这些executor不一定都是用来处理同一个component
Config conf = new Config();
conf.setNumWorkers(2); // use two worker processes
topologyBuilder.setSpout("blue-spout", new BlueSpout(), 2); // set parallelism hint to 2
topologyBuilder.setBolt("green-bolt", new GreenBolt(), 2)
.setNumTasks(4)
.shuffleGrouping("blue-spout");
topologyBuilder.setBolt("yellow-bolt", new YellowBolt(), 6)
.shuffleGrouping("green-bolt");
StormSubmitter.submitTopology(
"mytopology",
conf,
topologyBuilder.createTopology()
);
配置拓扑的并行度
1.工作进程的数量
工作进程的数量表示集群中不同节点的拓扑可以创建多少个工作进程。
配置参数是:TOPOLOGY_WORKERS
比如:在 storm.yaml 文件中 设置
topology.workers:1
也可以通过java API进行设置:
Config#setNumWorkers
2.执行器(线程)的数量
执行器的数量指的是每个组件产生多少个线程。
这个参数暂时只能通过java API进行配置:
TopologyBuilder#setSpout()
TopologyBuilder#setBolt()
3.任务的数量
任务的数量表示的是每个组件创建多少个任务。
配置选项:TOPOLOGY_TASKS
也可以通过java API进行配置:
ComponentConfigurationDeclarer#setNumTasks()
T setNumTasks(java.lang.Number val)
比如:在 storm.yaml 文件中 设置
topology.tasks:1
拓扑示例
下面我们定义一个名为mytopology的拓扑,由一个Spout组件(BlueSpout)、两个Bolt组件(GreenBolt和YellowBolt)共三个组件构成,代码如下:
Config conf = new Config();
conf.setNumWorkers(2);
topologyBuilder.setSpout("blue-spout", new BlueSpout(), 2);
topologyBuilder.setBolt("green-bolt", new GreenBolt(), 2)
.setNumTasks(4)
.shuffleGrouping("blue-spout");
topologyBuilder.setBolt("yellow-bolt", new YellowBolt(), 6)
.shuffleGrouping("green-bolt");
StormSubmitter.submitTopology(
"mytopology",
conf,
topologyBuilder.createTopology()
);
mytopology拓扑的描述如下:
**1.**拓扑将使用两个工作进程(Worker)。
**2.**Spout是id为“blue-spout”、并行度为2的BlueSpout实例 (产生两个执行器和两个任务)。
**3.**第一个Bolt的id为"green-bolt"、并行度为2、任务数为4、使用随机分组方式接收"blue-spout"所发射元组的GreenBolt实例(产生两个执行器和4个任务)。
**4.**第二个Bolt是id为"yellow-bolt"、并行度为6、使用随机分组方式接收"green-bolt"所发射元组的YellowBolt实例(产生6个执行器和6个任务)。
综上所述,该拓扑一共有两个工作进程(Worker),2+2+6=10个执行器(Executor),2+3+6=12个任务。因此,每个工作进程可以分配到10/2=5个执行器,12/2=6个任务。默认情况下,一个执行器执行一个任务,但是如果指定了任务的数目,则任务会平均分配到执行器中,因此,GreenBolt的实例"green-bolt"的一个执行器将会分配到4/2个任务。
mytopology的拓扑及其对应的资源分配如下图所示:
、
对于这个topology,
- 它包含3个component,1个spout,2个bolt
- 它包含2个worker process,10个executor thread,12个task
- 同颜色属于同一个component
动态设置拓扑的并发度
Storm支持在不重启Topolog的情况下,动态的改变(增减)worker process的数目和Executor的数目,称为rebalancing。有两种方式可以实现拓扑的再平衡:
**1.**使用Storm Web UI
2.使用Storm rebalance命令(推荐使用)
使用命令行的方式如下:
# 重新配置拓扑
# "mytopology" 拓扑使用5个Worker进程
# "blue-spout" Spout使用3个Executor
# "blue-spout" Bolt使用10个Executor
# storm rebalance mytopology -n 5 -e blue-spout=3 -e yellow-bolt=10
# 重新配置拓扑
# "mytopology" 拓扑使用5个Worker进程
# "blue-spout" Spout使用3个Executor
# "blue-spout" Bolt使用10个Executor
# storm rebalance mytopology -n 5 -e blue-spout=3 -e yellow-bolt=10