相比Hadoop的批处理,Storm的特点就是实时性。
Topology中所有的处理都由Bolt完成。Bolt可以完成任何事,比如:连接的过滤、聚合、访问文件/数据库、等等。Bolt从Spout中接收数据并进行处理,如果遇到复杂流的处理也可能将tuple发送给另一个Bolt进行处理。而Bolt中最重要的方法是execute(),以新的tuple作为参数接收。不管是Spout还是Bolt,如果将tuple发射成多个流,这些流都可以通过declareStream()来声明。
worker,进程数。
Executor,线程总数。
Task,具体的spout和bolt的实例个数。一个Executor可以负责1个或多个task。一般地,task数等于executor数。
分布式处理的主要思想就是把大的任务划分成多个子任务,它们在不同的机器或线程中并行处理,最后汇合。以统计班上同学的平均成绩为例,说明问题。
bolt如何设计?
因为分布式的原因,同一bolt类的多个线程之间不能有数据共享。分十个机器,编号为i的机器统计学号末尾为i的同学数和他们的总成绩,最后汇总。
如何控制每一个bolt实例接收哪些学号的数据呢?
结合上文,编号为i的bolt实例只接受学号末尾为i的数据。可以按照tuple的字段分组。
tuple传递是通过序列化,套接字传输,反序列化实现的。
所谓的grouping策略就是在Spout与Bolt、Bolt与Bolt之间传递Tuple的方式。总共有七种方式:
1)shuffleGrouping(随机分组)
2)fieldsGrouping(按照字段分组,在这里即是同一个单词只能发送给一个Bolt)
//declare与emit是一一对应的。 declarer.declareStream("http", new Fields("event", "key")); collector.emit("http", new Values(new MyClass(), key)); //设置bolt的时候指定按照哪个字段散列 builder.setBolt("httpCount", new AnalyseBolt()).fieldsGrouping("XX", "http", new Fields("key")); //接收到tuple时按指定字段取值 public void process(Tuple tuple, BasicOutputCollector collector) { tuple.getValueByField("event") instanceof MyClass }
8)customGrouping (自定义的Grouping)
要理解这个问题,需要看一下tuple在离开spout之后的生命周期。作为参考,下面是spout实现的接口
public interface ISpout extendsSerializable { void open(Map conf, TopologyContext context,SpoutOutputCollector collector); void close(); void nextTuple(); void ack(Object msgId); void fail(Object msgId); }
storm自带的一个仪表盘,见图1.
图1 storm自带的一个仪表盘
emitted,发射的tuple数。
transferred,若一个tuple被其他bolt读取,则transferred+1。
acked,tuple被完整处理。
failed,在处理过程中出现错误或超时的tuple数。超时参数可以设置。