Storm概述
1.结构
storm结构称为topology(拓扑),由stream(数据流),spout(喷嘴-数据流的生成者),bolt(阀门-数据流运算者)组成(参考图:Storm组成结构)。
不同于Hadoop中的job,Storm中的topology会一直运行下去,除非进程被杀死或取消部署。
2.Stream
Storm的核心数据结构是tuple(元组),本质上是包含了一个或多个键值对的列表。Stream是由无限制的tuple组成的序列。
3.spout
spout连接到数据源,将数据转化为一个个的tuple,并将tuple作为数据流进行发射。开发一个spout的主要工作就是利用API编写代码从数据源消费数据流。
spout的数据源可以有很多种来源:
web或者移动程序的点击流
社交网络的信息
传感器收集到的数据
应用程序产生的日志信息
spout通常只负责转换数据、发射数据,通常不会用于处理业务逻辑,从而可以很方便的实现spout的复用。
4.bolt
bolt主要负责数据的运算,将接收到的数据实施运算后,选择性的输出一个或多个数据流。
一个bolt可以接收多个由spout或其他bolt发射的数据流,从而可以组建出复杂的数据转换和处理的网络拓扑结构。
bolt常见的典型功能:
过滤
连接和聚合
计算
数据库的读写
Storm的并发机制
1.Storm集群中的topology由这四个主要部分组成:
(1)Nodes--服务器:配置在Storm集群中的一个服务器,会执行Topology的一部分运算,一个Storm集群中包含一个或者多个Node
(2)Workers--JVM虚拟机、进程:指一个Node上相互独立运作的JVM进程,每个Node可以配置运行一个或多个worker。一个Topology会分配到一个或者多个worker上运行。
(3)Executeor--线程:指一个worker的jvm中运行的java线程。多个task可以指派给同一个executer来执行。除非是明确指定,Storm默认会给每个executor分配一个task。
(4)Task--bolt/spout实例:task是sqout和bolt的实例,他们的nextTuple()和execute()方法会被executors线程调用执行。
大多数情况下,除非明确指定,Storm的默认并发设置值是1。即,一台服务器(node),为topology分配一个worker,每个executer执行一个task。参看图(Storm默认并发机制)
此时唯一的并发机制出现在线程级。
在单机模式下增加并发的方式可以体现在分配更多的worker和executer给topology。
**单机模式下,增加Node的数量不会有任何提升速度的效果。
2.增加worker
可以通过API和修改配置两种方式修改分配给topology的woker数量。
Config config = new Config();
config.setNumWorkers(2);
3.增加Executor
builder.setSpout(spout_id,spout,executor_num)
builder.setBolt(bolt_id,bolt,executor_num)
4.增加Task
builder.setSpout(…).setNumTasks(task_num);
builder.setBolt(…).setNumTasks(task_num);
5.数据流分组
数据流分组方式定义了数据如何进行分发。
Storm内置了七种数据流分组方式:
Shuffle Grouping(随机分组)
随机分发数据流中的tuple给bolt中的各个task,每个task接收到的tuple数量相同。
Fields Grouping(按字段分组)
根据指定字段的值进行分组。指定字段具有相同值的tuple会路由到同一个bolt中的task中。
All Grouping(全复制分组)
所有的tuple赋值后分发给所有的bolt task。
Globle Grouping(全局分组)
这种分组方式将所有的tuple路由到唯一一个task上,Storm按照最小task id来选取接受数据的task。
这种分组方式下配置bolt的task的并发度没有意义。
这种方式会导致所有tuple都发送到一个JVM实例上,可能会引起Strom集群中某个JVM或者服务器出现性能瓶颈或崩溃。
None Grouping(不分组)
在功能上和随机分组相同,为将来预留。
Direct Grouping(指向型分组)
数据源会通过emitDirect()方法来判断一个tuple应该由哪个Strom组件来接受。只能在声明了是指向型数据流上使用。
Local or shuffle Grouping(本地或随机分组)
和随机分组类似,但是,会将tuple分发给同一个worker内的bolt task,其他情况下采用随机分组方式。
这种方式可以减少网络传输,从而提高topology的性能。
**另外可以自定义数据流分组方式
写类实现CustomStreamGrouping接口
代码:
/**
* 自定义数据流分组方式
* @author park
*
*/
public class MyStreamGrouping implements CustomStreamGrouping {
/**
* 运行时调用,用来初始化分组信息
* context:topology上下文对象
* stream:待分组数据流属性
* targetTasks:所有待选task的标识符列表
*
*/
@Override
public void prepare(WorkerTopologyContext context, GlobalStreamId stream, List<Integer> targetTasks) {
}
/**
* 核心方法,进行task选择
* taskId:发送tuple的组件id
* values:tuple的值
* 返回值要发往哪个task
*/
@Override
public List<Integer> chooseTasks(int taskId, List<Object> values) {
return null;
}
}