一、Storm概述
Storm是一个开源的分布式实时计算系统,可以简单、可靠的处理大量的数据流。Storm有很多使用场景:如实时分析,在线机器学习,持续计算,分布式RPC,ETL等等。Storm支持水平扩展,具有高容错性,保证每个消息都会得到处理,而且处理速度很快(在一个小集群中,每个结点每秒可以处理数以百万计的消息)。Storm的部署和运维都很便捷,而且更为重要的是可以使用任意编程语言来开发应用。
二、Storm详解
1.结构
storm结构称为topology(拓扑),由stream(数据流),spout(喷嘴-数据流的生成者),bolt(阀门-数据流运算者)组成。
不同于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常见的典型功能:
过滤
连接和聚合
计算
数据库的读写
三、入门案例
0.案例结构和准备
结构:
案例:Word Count案例
语句Spout --> 语句分隔Bolt --> 单词计数Bolt --> 上报Bolt
准备:
编写程序前先导入jar包:资源
1.语句生成Spout - SentenceSpout
作为入门案例,我们直接从一个数组中不断读取语句,作为数据来源。
SentenceSpout不断读取语句将其作为数据来源,组装成单值tuple(键名sentence,键值为String格式的语句)向后发射。
{"sentence":"i am so shuai!"}
package com.liming;
import java.util.Map;
import backtype.storm.spout.SpoutOutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichSpout;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Values;
import backtype.storm.utils.Utils;
/**
* BaseRichSpout类是ISpout接口和IComponent接口的一个简便的实现。采用了适配器模式,对用不到的方法提供了默认实现。
*/
public class SentenceSpout extends BaseRichSpout{
private SpoutOutputCollector collector;
private String[] Sentence ={
"i am so shuai",
"do you like me",
"are you sure do not like me",
"i am sure"
};
private int index = 0;
/**
* ISpout接口中定义的方法
* 所有Spout组件在初始化时都会调用这个方法。
* map 包含了Storm配置信息
* context 提供了topology中的组件信息
* collector 提供了发射tuple的方法
*/
@Override
public void open(Map map, TopologyContext context, SpoutOutputCollector collector) {
this.collector = collector;
}
/**
* 覆盖自BaseRichSpout中的方法
* 核心方法
* Storm通过调用此方法向发射tuple
*/
@Override
public void nextTuple() {
this.collector.emit(new Values(Sentence[index]));
index = (index + 1 >=Sentence.length) ? 0 : index+1;
Utils.sleep(1000);
}
/**
* IComponent接口中定义的方法
* 所有的Storm组件(spout、bolt)都要实现此接口。
* 此方法告诉Storm当前组件会发射哪些数据流,每个数据流中的tuple中包含哪些字段。
*/
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("sentence"));
}
}
2..语句分隔Bolt -- SplitSenetenceBolt
语句分隔Bolt订阅SentenceSpout发射的tuple,每接收到一个tuple就获取"sentence"对应的值,然后将得到的语句按照空格切分为一个个单词。然后将每个单词向后发射一个tuple。
{"word":"I"}
{"word":"am"}
{"word":"so"}
{"word":"shuai"}
package com.liming;
import java.util.Map;
import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichBolt;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;
/**
* BaseRichBolt 是IComponent 和 IBolt接口的一个简单实现。采用了适配器模式,对用不到的方法提供了默认实现。
*/
public class SplitSenetenceBolt extends BaseRichBolt{
private OutputCollector collector;
/**
* 定义在IBolt中的方法
* 在bolt初始化时调用,用来初始化bolt
* stormConf 包含了Storm配置信息
* context 提供了topology中的组件信息
* collector 提供了发射tuple的方法
*/
@Override
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
this.collector = collector;
}
/**
* 覆盖自BaseRichBolt中的方法
* 核心方法
* Storm通过调用此方法向发射tuple
*/
@Override
public void execute(Tuple input) {
String sentence = input.getStringByField("sentence");
String[] split = sentence.split(" ");
for (String string : split) {
collector.emit(new Values(string));
}
}
/**
* IComponent接口中定义的方法
* 所有的Storm组件(spout、bolt)都要实现此接口。
* 此方法告诉Storm当前组件会发射哪些数据流,每个数据流中的tuple中包含哪些字段。
*/
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word"));
}
}
3.单词计数Bolt -- WordCountBolt
单词计数Bolt订阅SplitSentenceBolt的输出,保存每个特定单词出现次数,当接收到一个新的tuple,会将对应单词计数加一,并向后发送该单词的当前计数。
{"word":"I","count":3}
package com.liming;
import java.util.HashMap;
import java.util.Map;
import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichBolt;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;
public class WordCountBolt extends BaseRichBolt{
private OutputCollector collector = null;
private HashMap<String,Long> counts = null;
/**
* 注意:
* 所有的序列化操作最好都在prepare方法中进行
* 原因:
* Storm在工作时会将所有的bolt和spout组件先进行序列化,然后发送到集群中,如果在序列化之前创建过任何无法序列化的对象都会造成序列化时抛出NotSerializableException。
* 此处的HashMap本身是可以序列化的所以不会有这个问题,但是有必要养成这样的习惯 。
*/
@Override
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
this.collector = collector;
this.counts = new HashMap<String,Long>();
}
@Override
public void execute(Tuple input) {
String word = input.getStringByField("word");
this.counts.put(word, counts.containsKey(word)?counts.get(word)+1:1);
this.collector.emit(new Values(word,counts.get(word)));
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word","count"));
}
}
4.上报Bolt -- ReportBolt
上报Bolt订阅WordCountBolt类的输出,内部维护一份所有单词的对应计数的表,当接收到一个tuple时,上报Bolt会更新表中的计数数据,并将值打印到终端。
package com.liming;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichBolt;
import backtype.storm.tuple.Tuple;
/**
* 此Bolt处于数据流的末端,所以只接受tuple而不发射任何数据流。
*/
public class ReportBolt extends BaseRichBolt{
private HashMap<String, Long> counts = null;
@Override
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
this.counts = new HashMap<String,Long>();
}
@Override
public void execute(Tuple input) {
String word = input.getStringByField("word");
Long count = input.getLongByField("count");
counts.put(word, count);
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
//处于流末端的tuple,没有任何输出数据流,所以此方法为空
}
/**
* Storm会在终止一个Bolt之前调用此方法。
* 此方法通常用来在Bolt退出之前释放资源。
* 此处我们用来输出统计结果到控制台。
* 注意:真正集群环境下,cleanup()方法是不可靠的,不能保证一定执行,后续会讨论。
*/
@Override
public void cleanup() {
System.out.println("----------统计结果-------------");
List<String> keys = new ArrayList<String>();
keys.addAll(counts.keySet());
Collections.sort(keys);
for (String string : keys) {
System.out.println(string+":"+counts.get(string));
}
System.out.println("-------------------------------");
}
}
5.单词计数Topology
通过main方法组装处理流程。
此处使用单机模式来测试。
package com.liming;
import backtype.storm.Config;
import backtype.storm.LocalCluster;
import backtype.storm.topology.TopologyBuilder;
import backtype.storm.tuple.Fields;
public class WordCountTopology {
private static final String SENTENCE_SPOUT_ID = "sentence-spout";
private static final String SPLIT_BOLT = "split-bolt";
private static final String COUNT_BOLT = "count-bolt";
private static final String REPORT_BOLT = "report-bolt";
private static final String TOPOLOGY_NAME = "wordcount-topology";
public static void main(String[] args) throws Exception {
//--实例化Spout和Bolt
SentenceSpout spout = new SentenceSpout();
SplitSenetenceBolt splitSenetenceBolt = new SplitSenetenceBolt();
WordCountBolt countBolt = new WordCountBolt();
ReportBolt reportBolt = new ReportBolt();
//--创建TopologyBuilder类实例
TopologyBuilder builder = new TopologyBuilder();
//--注册SentenceSpout
builder.setSpout(SENTENCE_SPOUT_ID, spout);
//--注册SplitSentenceBolt,订阅SentenceSpout发送的tuple
//此处使用了shuffleGrouping方法,此方法指定所有的tuple随机均匀的分发给SplitSentenceBolt的实例。
builder.setBolt(SPLIT_BOLT, splitSenetenceBolt).shuffleGrouping(SENTENCE_SPOUT_ID);
//--注册WordCountBolt,,订阅SplitSentenceBolt发送的tuple
//此处使用了filedsGrouping方法,此方法可以将指定名称的tuple路由到同一个WordCountBolt实例中
builder.setBolt(COUNT_BOLT, countBolt).fieldsGrouping(SPLIT_BOLT, new Fields("word"));
//--注册ReprotBolt,订阅WordCountBolt发送的tuple
//此处使用了globalGrouping方法,表示所有的tuple都路由到唯一的ReprotBolt实例中
builder.setBolt(REPORT_BOLT, reportBolt).globalGrouping(COUNT_BOLT);
//--创建配置对象
Config conf = new Config();
//--创建代表集群的对象,LocalCluster表示在本地开发环境来模拟一个完整的Storm集群
//本地模式是开发和测试的简单方式,省去了在分布式集群中反复部署的开销
//另外可以执行断点调试非常的便捷
LocalCluster cluster = new LocalCluster();
//--提交Topology给集群运行
cluster.submitTopology(TOPOLOGY_NAME, conf, builder.createTopology());
//--运行10秒钟后杀死Topology关闭集群
Thread.sleep(1000 * 10);
cluster.killTopology(TOPOLOGY_NAME);
cluster.shutdown();
}
}
执行结果:每个单词到统计到了
四、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;
}
}
五、Storm的可靠性
1.每条数据都被处理过、2.消息要顺序处理、3.每条消息只被处理一次
以下介绍可靠性1(每条数据都要被处理到):ack、faile机制保证
Storm提供了数据流处理时的可靠性,所谓的可靠性是指spout发送的每个tuple都能够执行完整的处理过程。
1.spout的可靠性
spout需要记录它发射出去的tuple,当下游bolt处理tuple或子tuple失败时,spout能够重新发射该tuple。
bolt在处理tuple或子tuple时,无论是否成功都需要向上游节点进行报告或者报错。
而在ISpout接口中定义了三个可靠性相关的API:
nextTuple
ack
fail
每个bolt都要向上一级负责报告自己的处理结果,如果spout的直接子bolt,都向spout进行了确认应答,表明后续处理都完成,则spout会调用ack方法来表明该消息已经完全处理了。如果任何一个bolt处理tuple报错,或者处理超时,spout会调用fail方法。
2.bolt的可靠性
在发射衍生的tuple时,需要锚定下一级的tuple。
子bolt处理消息成功或者失败时分别发送确认应答或者报错给父tuple或父spout。
锚定的意思是建立tuple和衍生出的tuple之间的对应关系,这样下游的bolt可以通过应答确认/报错或超时来加入到tuple树结构中来。
collector.emit(tuple,new Values(word));
**此方法具有重载的方法,不锚定子节点,这种方式不会进行锚定操作,非锚定的tuple不会对数据流的可靠性起作用,如果一个非锚定的tuple在下游处理失败,原始的根tuple不会重新发送。
collector.emit(new Values(word));
当处理完成或者发送了新tuple之后,可靠数据流中的bolt需要应答读入的tuple:
this.collector.ack(tuple);
如果处理失败,则spout必须发射tuple,bolt就要明确的处理失败的tuple报错:
this.collector.fail(tuple);
如果因为超时的原因,或者显示调用OutputCollector.fail()方法,spout都会重新发送原始tuple。
如果将上面案例中的SplitSenetenceBolt类替换如下
package com.liming;
import java.util.Map;
import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichBolt;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;
/**
* BaseRichBolt 是IComponent 和 IBolt接口的一个简单实现。采用了适配器模式,对用不到的方法提供了默认实现。
*/
public class SplitSenetenceBolt extends BaseRichBolt{
private OutputCollector collector;
/**
* 定义在IBolt中的方法
* 在bolt初始化时调用,用来初始化bolt
* stormConf 包含了Storm配置信息
* context 提供了topology中的组件信息
* collector 提供了发射tuple的方法
*/
@Override
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
this.collector = collector;
}
/**
* 覆盖自BaseRichBolt中的方法
* 核心方法
* Storm通过调用此方法向发射tuple
*/
@Override
public void execute(Tuple input) {
String sentence = input.getStringByField("sentence");
if("i am so shuai".equals(sentence)){
return;
}
String[] split = sentence.split(" ");
for (String string : split) {
collector.emit(new Values(string));
}
}
/**
* IComponent接口中定义的方法
* 所有的Storm组件(spout、bolt)都要实现此接口。
* 此方法告诉Storm当前组件会发射哪些数据流,每个数据流中的tuple中包含哪些字段。
*/
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word"));
}
}
在代码中加入了一个人为异常
if("i am so shuai".equals(sentence)){
return;
}
发现shuai没有被统计
因此上面案例不可靠:因为有数据没有被处理到
Storm提供了数据流处理时的可靠性,所谓的可靠性是指spout发送的每个tuple都能够执行完整的处理过程。
1.spout的可靠性
spout需要记录它发射出去的tuple,当下游bolt处理tuple或子tuple失败时,spout能够重新发射该tuple。
bolt在处理tuple或子tuple时,无论是否成功都需要向上游节点进行报告或者报错。
而在ISpout接口中定义了三个可靠性相关的API:
nextTuple
ack
fail
每个bolt都要向上一级负责报告自己的处理结果,如果spout的直接子bolt,都向spout进行了确认应答,表明后续处理都完成,则spout会调用ack方法来表明该消息已经完全处理了。如果任何一个bolt处理tuple报错,或者处理超时,spout会调用fail方法。
2.bolt的可靠性
在发射衍生的tuple时,需要锚定下一级的tuple。
子bolt处理消息成功或者失败时分别发送确认应答或者报错给父tuple或父spout。
锚定的意思是建立tuple和衍生出的tuple之间的对应关系,这样下游的bolt可以通过应答确认/报错或超时来加入到tuple树结构中来。
collector.emit(tuple,new Values(word));
**此方法具有重载的方法,不锚定子节点,这种方式不会进行锚定操作,非锚定的tuple不会对数据流的可靠性起作用,如果一个非锚定的tuple在下游处理失败,原始的根tuple不会重新发送。
collector.emit(new Values(word));
当处理完成或者发送了新tuple之后,可靠数据流中的bolt需要应答读入的tuple:
this.collector.ack(tuple);
如果处理失败,则spout必须发射tuple,bolt就要明确的处理失败的tuple报错:
this.collector.fail(tuple);
如果因为超时的原因,或者显示调用OutputCollector.fail()方法,spout都会重新发送原始tuple。
修改案例如下:
package com.liming;
import java.util.Map;
import backtype.storm.spout.SpoutOutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichSpout;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Values;
import backtype.storm.utils.Utils;
/**
* BaseRichSpout类是ISpout接口和IComponent接口的一个简便的实现。采用了适配器模式,对用不到的方法提供了默认实现。
*/
public class SentenceSpout extends BaseRichSpout{
private SpoutOutputCollector collector;
private String[] Sentence ={
"i am so shuai",
"do you like me",
"are you sure do not like me",
"i am sure"
};
private int index = 0;
/**
* ISpout接口中定义的方法
* 所有Spout组件在初始化时都会调用这个方法。
* map 包含了Storm配置信息
* context 提供了topology中的组件信息
* collector 提供了发射tuple的方法
*/
@Override
public void open(Map map, TopologyContext context, SpoutOutputCollector collector) {
this.collector = collector;
}
/**
* 覆盖自BaseRichSpout中的方法
* 核心方法
* Storm通过调用此方法向发射tuple
*/
@Override
public void nextTuple() {
// this.collector.emit(new Values(Sentence[index]));
// index = (index + 1 >=Sentence.length) ? 0 : index+1;
// Utils.sleep(1000);
if(index<Sentence.length){
String s = Sentence[index];
this.collector.emit(new Values(s), index);
index++;
}
Utils.sleep(1000);
}
/**
* IComponent接口中定义的方法
* 所有的Storm组件(spout、bolt)都要实现此接口。
* 此方法告诉Storm当前组件会发射哪些数据流,每个数据流中的tuple中包含哪些字段。
*/
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("sentence"));
}
@Override
public void fail(Object msgId) {
System.out.println("消息:"+Sentence[(int)msgId]+"----处理失败,,,,尝试重发");
this.collector.emit(new Values(Sentence[(int)msgId]),msgId);
}
@Override
public void ack(Object msgId) {
System.out.println("消息:"+Sentence[(int)msgId]+"----处理成功");
}
}
package com.liming;
import java.util.Map;
import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichBolt;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;
/**
* BaseRichBolt 是IComponent 和 IBolt接口的一个简单实现。采用了适配器模式,对用不到的方法提供了默认实现。
*/
public class SplitSenetenceBolt extends BaseRichBolt{
private OutputCollector collector;
/**
* 定义在IBolt中的方法
* 在bolt初始化时调用,用来初始化bolt
* stormConf 包含了Storm配置信息
* context 提供了topology中的组件信息
* collector 提供了发射tuple的方法
*/
@Override
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
this.collector = collector;
}
/**
* 覆盖自BaseRichBolt中的方法
* 核心方法
* Storm通过调用此方法向发射tuple
*/
int count = 0;
@Override
public void execute(Tuple input) {
try {
String sentence = input.getStringByField("sentence");
if("i am so shuai".equals(sentence)&&count<3){
count++;
throw new RuntimeException("```````````异常出现············");
}
String[] split = sentence.split(" ");
for (String string : split) {
collector.emit(input,new Values(string));
}
collector.ack(input);
} catch (Exception e) {
e.printStackTrace();
collector.fail(input);
}
}
/**
* IComponent接口中定义的方法
* 所有的Storm组件(spout、bolt)都要实现此接口。
* 此方法告诉Storm当前组件会发射哪些数据流,每个数据流中的tuple中包含哪些字段。
*/
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word"));
}
}
package com.liming;
import java.util.HashMap;
import java.util.Map;
import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichBolt;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;
public class WordCountBolt extends BaseRichBolt{
private OutputCollector collector = null;
private HashMap<String,Long> counts = null;
/**
* 注意:
* 所有的序列化操作最好都在prepare方法中进行
* 原因:
* Storm在工作时会将所有的bolt和spout组件先进行序列化,然后发送到集群中,如果在序列化之前创建过任何无法序列化的对象都会造成序列化时抛出NotSerializableException。
* 此处的HashMap本身是可以序列化的所以不会有这个问题,但是有必要养成这样的习惯 。
*/
@Override
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
this.collector = collector;
this.counts = new HashMap<String,Long>();
}
@Override
public void execute(Tuple input) {
try {
String word = input.getStringByField("word");
this.counts.put(word, counts.containsKey(word)?counts.get(word)+1:1);
this.collector.emit(input,new Values(word,counts.get(word)));
collector.ack(input);
} catch (Exception e) {
collector.fail(input);
}
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word","count"));
}
}
package com.liming;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichBolt;
import backtype.storm.tuple.Tuple;
/**
* 此Bolt处于数据流的末端,所以只接受tuple而不发射任何数据流。
*/
public class ReportBolt extends BaseRichBolt{
private HashMap<String, Long> counts = null;
private OutputCollector collector;
@Override
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
this.counts = new HashMap<String,Long>();
this.collector = collector;
}
@Override
public void execute(Tuple input) {
try {
String word = input.getStringByField("word");
Long count = input.getLongByField("count");
counts.put(word, count);
System.out.println("单词数量发生变化:"+word+"~~~~~~~~"+count);
collector.ack(input);
} catch (Exception e) {
collector.fail(input);
}
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
//处于流末端的tuple,没有任何输出数据流,所以此方法为空
}
/**
* Storm会在终止一个Bolt之前调用此方法。
* 此方法通常用来在Bolt退出之前释放资源。
* 此处我们用来输出统计结果到控制台。
* 注意:真正集群环境下,cleanup()方法是不可靠的,不能保证一定执行,后续会讨论。
*/
@Override
public void cleanup() {
System.out.println("----------统计结果-------------");
List<String> keys = new ArrayList<String>();
keys.addAll(counts.keySet());
Collections.sort(keys);
for (String string : keys) {
System.out.println(string+":"+counts.get(string));
}
System.out.println("-------------------------------");
}
}
package com.liming;
import backtype.storm.Config;
import backtype.storm.LocalCluster;
import backtype.storm.topology.TopologyBuilder;
import backtype.storm.tuple.Fields;
public class WordCountTopology {
private static final String SENTENCE_SPOUT_ID = "sentence-spout";
private static final String SPLIT_BOLT = "split-bolt";
private static final String COUNT_BOLT = "count-bolt";
private static final String REPORT_BOLT = "report-bolt";
private static final String TOPOLOGY_NAME = "wordcount-topology";
public static void main(String[] args) throws Exception {
//--实例化Spout和Bolt
SentenceSpout spout = new SentenceSpout();
SplitSenetenceBolt splitSenetenceBolt = new SplitSenetenceBolt();
WordCountBolt countBolt = new WordCountBolt();
ReportBolt reportBolt = new ReportBolt();
//--创建TopologyBuilder类实例
TopologyBuilder builder = new TopologyBuilder();
//--注册SentenceSpout
builder.setSpout(SENTENCE_SPOUT_ID, spout);
//--注册SplitSentenceBolt,订阅SentenceSpout发送的tuple
//此处使用了shuffleGrouping方法,此方法指定所有的tuple随机均匀的分发给SplitSentenceBolt的实例。
builder.setBolt(SPLIT_BOLT, splitSenetenceBolt).shuffleGrouping(SENTENCE_SPOUT_ID);
//--注册WordCountBolt,,订阅SplitSentenceBolt发送的tuple
//此处使用了filedsGrouping方法,此方法可以将指定名称的tuple路由到同一个WordCountBolt实例中
builder.setBolt(COUNT_BOLT, countBolt).fieldsGrouping(SPLIT_BOLT, new Fields("word"));
//--注册ReprotBolt,订阅WordCountBolt发送的tuple
//此处使用了globalGrouping方法,表示所有的tuple都路由到唯一的ReprotBolt实例中
builder.setBolt(REPORT_BOLT, reportBolt).globalGrouping(COUNT_BOLT);
//--创建配置对象
Config conf = new Config();
//--创建代表集群的对象,LocalCluster表示在本地开发环境来模拟一个完整的Storm集群
//本地模式是开发和测试的简单方式,省去了在分布式集群中反复部署的开销
//另外可以执行断点调试非常的便捷
LocalCluster cluster = new LocalCluster();
//--提交Topology给集群运行
cluster.submitTopology(TOPOLOGY_NAME, conf, builder.createTopology());
//--运行10秒钟后杀死Topology关闭集群
Thread.sleep(1000 * 10);
cluster.killTopology(TOPOLOGY_NAME);
cluster.shutdown();
}
}
经过失败重发后发现最终shuai被统计,证明使用这个机制可以保证每条数据都能被处理成功
6065 [Thread-12-sentence-spout] INFO backtype.storm.daemon.executor - Activating spout sentence-spout:(4)
6069 [Thread-4] INFO backtype.storm.daemon.executor - Loading executor split-bolt:[5 5]
6071 [Thread-4] INFO backtype.storm.daemon.executor - Loaded executor tasks split-bolt:[5 5]
6073 [Thread-4] INFO backtype.storm.daemon.executor - Finished loading executor split-bolt:[5 5]
6076 [Thread-14-split-bolt] INFO backtype.storm.daemon.executor - Preparing bolt split-bolt:(5)
6078 [Thread-14-split-bolt] INFO backtype.storm.daemon.executor - Prepared bolt split-bolt:(5)
java.lang.RuntimeException: ```````````异常出现············
at com.liming.SplitSenetenceBolt.execute(SplitSenetenceBolt.java:41)
at backtype.storm.daemon.executor$fn__3441$tuple_action_fn__3443.invoke(executor.clj:633)
at backtype.storm.daemon.executor$mk_task_receiver$fn__3364.invoke(executor.clj:401)
at backtype.storm.disruptor$clojure_handler$reify__1447.onEvent(disruptor.clj:58)
at backtype.storm.utils.DisruptorQueue.consumeBatchToCursor(DisruptorQueue.java:120)
at backtype.storm.utils.DisruptorQueue.consumeBatchWhenAvailable(DisruptorQueue.java:99)
at backtype.storm.disruptor$consume_batch_when_available.invoke(disruptor.clj:80)
at backtype.storm.daemon.executor$fn__3441$fn__3453$fn__3500.invoke(executor.clj:748)
at backtype.storm.util$async_loop$fn__464.invoke(util.clj:463)
at clojure.lang.AFn.run(AFn.java:24)
at java.lang.Thread.run(Unknown Source)
6086 [Thread-4] INFO backtype.storm.daemon.executor - Loading executor __system:[-1 -1]
6088 [Thread-4] INFO backtype.storm.daemon.executor - Loaded executor tasks __system:[-1 -1]
6091 [Thread-4] INFO backtype.storm.daemon.executor - Finished loading executor __system:[-1 -1]
6095 [Thread-16-__system] INFO backtype.storm.daemon.executor - Preparing bolt __system:(-1)
6101 [Thread-16-__system] INFO backtype.storm.daemon.executor - Prepared bolt __system:(-1)
6105 [Thread-4] INFO backtype.storm.daemon.executor - Loading executor __acker:[1 1]
6106 [Thread-4] INFO backtype.storm.daemon.executor - Loaded executor tasks __acker:[1 1]
6108 [Thread-4] INFO backtype.storm.daemon.executor - Timeouts disabled for executor __acker:[1 1]
6108 [Thread-18-__acker] INFO backtype.storm.daemon.executor - Preparing bolt __acker:(1)
6108 [Thread-4] INFO backtype.storm.daemon.executor - Finished loading executor __acker:[1 1]
6108 [Thread-4] INFO backtype.storm.daemon.worker - Launching receive-thread for 83b4eb09-c8a0-4932-aba0-0a8015dc4b50:1024
6110 [Thread-18-__acker] INFO backtype.storm.daemon.executor - Prepared bolt __acker:(1)
6116 [Thread-19-worker-receiver-thread-0] INFO backtype.storm.messaging.loader - Starting receive-thread: [stormId: wordcount-topology-1-1524063976, port: 1024, thread-id: 0 ]
6123 [Thread-4] INFO backtype.storm.daemon.worker - Worker has topology config {"storm.id" "wordcount-topology-1-1524063976", "dev.zookeeper.path" "/tmp/dev-storm-zookeeper", "topology.tick.tuple.freq.secs" nil, "topology.builtin.metrics.bucket.size.secs" 60, "topology.fall.back.on.java.serialization" true, "topology.max.error.report.per.interval" 5, "zmq.linger.millis" 0, "topology.skip.missing.kryo.registrations" true, "storm.messaging.netty.client_worker_threads" 1, "ui.childopts" "-Xmx768m", "storm.zookeeper.session.timeout" 20000, "nimbus.reassign" true, "topology.trident.batch.emit.interval.millis" 50, "storm.messaging.netty.flush.check.interval.ms" 10, "nimbus.monitor.freq.secs" 10, "logviewer.childopts" "-Xmx128m", "java.library.path" "/usr/local/lib:/opt/local/lib:/usr/lib", "topology.executor.send.buffer.size" 1024, "storm.local.dir" "C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\c901ad6c-67e7-45f3-9f07-1ccb2fbb1937", "storm.messaging.netty.buffer_size" 5242880, "supervisor.worker.start.timeout.secs" 120, "topology.enable.message.timeouts" true, "nimbus.cleanup.inbox.freq.secs" 600, "nimbus.inbox.jar.expiration.secs" 3600, "drpc.worker.threads" 64, "storm.meta.serialization.delegate" "backtype.storm.serialization.DefaultSerializationDelegate", "topology.worker.shared.thread.pool.size" 4, "nimbus.host" "localhost", "storm.messaging.netty.min_wait_ms" 100, "storm.zookeeper.port" 2000, "transactional.zookeeper.port" nil, "topology.executor.receive.buffer.size" 1024, "transactional.zookeeper.servers" nil, "storm.zookeeper.root" "/storm", "storm.zookeeper.retry.intervalceiling.millis" 30000, "supervisor.enable" true, "storm.messaging.netty.server_worker_threads" 1, "storm.zookeeper.servers" ["localhost"], "transactional.zookeeper.root" "/transactional", "topology.acker.executors" nil, "topology.kryo.decorators" (), "topology.name" "wordcount-topology", "topology.transfer.buffer.size" 1024, "topology.worker.childopts" nil, "drpc.queue.size" 128, "worker.childopts" "-Xmx768m", "supervisor.heartbeat.frequency.secs" 5, "topology.error.throttle.interval.secs" 10, "zmq.hwm" 0, "drpc.port" 3772, "supervisor.monitor.frequency.secs" 3, "drpc.childopts" "-Xmx768m", "topology.receiver.buffer.size" 8, "task.heartbeat.frequency.secs" 3, "topology.tasks" nil, "storm.messaging.netty.max_retries" 300, "topology.spout.wait.strategy" "backtype.storm.spout.SleepSpoutWaitStrategy", "nimbus.thrift.max_buffer_size" 1048576, "topology.max.spout.pending" nil, "storm.zookeeper.retry.interval" 1000, "topology.sleep.spout.wait.strategy.time.ms" 1, "nimbus.topology.validator" "backtype.storm.nimbus.DefaultTopologyValidator", "supervisor.slots.ports" (1024 1025 1026), "topology.environment" nil, "topology.debug" false, "nimbus.task.launch.secs" 120, "nimbus.supervisor.timeout.secs" 60, "topology.kryo.register" nil, "topology.message.timeout.secs" 30, "task.refresh.poll.secs" 10, "topology.workers" 1, "supervisor.childopts" "-Xmx256m", "nimbus.thrift.port" 6627, "topology.stats.sample.rate" 0.05, "worker.heartbeat.frequency.secs" 1, "topology.tuple.serializer" "backtype.storm.serialization.types.ListDelegateSerializer", "topology.disruptor.wait.strategy" "com.lmax.disruptor.BlockingWaitStrategy", "topology.multilang.serializer" "backtype.storm.multilang.JsonSerializer", "nimbus.task.timeout.secs" 30, "storm.zookeeper.connection.timeout" 15000, "topology.kryo.factory" "backtype.storm.serialization.DefaultKryoFactory", "drpc.invocations.port" 3773, "logviewer.port" 8000, "zmq.threads" 1, "storm.zookeeper.retry.times" 5, "topology.worker.receiver.thread.count" 1, "storm.thrift.transport" "backtype.storm.security.auth.SimpleTransportPlugin", "topology.state.synchronization.timeout.secs" 60, "supervisor.worker.timeout.secs" 30, "nimbus.file.copy.expiration.secs" 600, "storm.messaging.transport" "backtype.storm.messaging.netty.Context", "logviewer.appender.name" "A1", "storm.messaging.netty.max_wait_ms" 1000, "drpc.request.timeout.secs" 600, "storm.local.mode.zmq" false, "ui.port" 8080, "nimbus.childopts" "-Xmx1024m", "storm.cluster.mode" "local", "topology.max.task.parallelism" nil, "storm.messaging.netty.transfer.batch.size" 262144, "topology.classpath" nil}
6123 [Thread-4] INFO backtype.storm.daemon.worker - Worker a4988a3f-148a-4f74-ab48-7eb3f5a8ac86 for storm wordcount-topology-1-1524063976 on 83b4eb09-c8a0-4932-aba0-0a8015dc4b50:1024 has finished loading
消息:i am so shuai----处理失败,,,,尝试重发
java.lang.RuntimeException: ```````````异常出现············
at com.liming.SplitSenetenceBolt.execute(SplitSenetenceBolt.java:41)
at backtype.storm.daemon.executor$fn__3441$tuple_action_fn__3443.invoke(executor.clj:633)
at backtype.storm.daemon.executor$mk_task_receiver$fn__3364.invoke(executor.clj:401)
at backtype.storm.disruptor$clojure_handler$reify__1447.onEvent(disruptor.clj:58)
at backtype.storm.utils.DisruptorQueue.consumeBatchToCursor(DisruptorQueue.java:125)
at backtype.storm.utils.DisruptorQueue.consumeBatchWhenAvailable(DisruptorQueue.java:99)
at backtype.storm.disruptor$consume_batch_when_available.invoke(disruptor.clj:80)
at backtype.storm.daemon.executor$fn__3441$fn__3453$fn__3500.invoke(executor.clj:748)
at backtype.storm.util$async_loop$fn__464.invoke(util.clj:463)
at clojure.lang.AFn.run(AFn.java:24)
at java.lang.Thread.run(Unknown Source)
单词数量发生变化:do~~~~~~~~1
单词数量发生变化:you~~~~~~~~1
单词数量发生变化:like~~~~~~~~1
单词数量发生变化:me~~~~~~~~1
java.lang.RuntimeException: ```````````异常出现············
消息:i am so shuai----处理失败,,,,尝试重发
at com.liming.SplitSenetenceBolt.execute(SplitSenetenceBolt.java:41)
at backtype.storm.daemon.executor$fn__3441$tuple_action_fn__3443.invoke(executor.clj:633)
at backtype.storm.daemon.executor$mk_task_receiver$fn__3364.invoke(executor.clj:401)
at backtype.storm.disruptor$clojure_handler$reify__1447.onEvent(disruptor.clj:58)
at backtype.storm.utils.DisruptorQueue.consumeBatchToCursor(DisruptorQueue.java:125)
at backtype.storm.utils.DisruptorQueue.consumeBatchWhenAvailable(DisruptorQueue.java:99)
at backtype.storm.disruptor$consume_batch_when_available.invoke(disruptor.clj:80)
at backtype.storm.daemon.executor$fn__3441$fn__3453$fn__3500.invoke(executor.clj:748)
at backtype.storm.util$async_loop$fn__464.invoke(util.clj:463)
at clojure.lang.AFn.run(AFn.java:24)
at java.lang.Thread.run(Unknown Source)
消息:do you like me----处理成功
单词数量发生变化:are~~~~~~~~1
单词数量发生变化:you~~~~~~~~2
单词数量发生变化:sure~~~~~~~~1
单词数量发生变化:do~~~~~~~~2
单词数量发生变化:not~~~~~~~~1
单词数量发生变化:like~~~~~~~~2
单词数量发生变化:me~~~~~~~~2
消息:i am so shuai----处理失败,,,,尝试重发
消息:are you sure do not like me----处理成功
单词数量发生变化:i~~~~~~~~1
单词数量发生变化:am~~~~~~~~1
单词数量发生变化:so~~~~~~~~1
单词数量发生变化:shuai~~~~~~~~1
单词数量发生变化:i~~~~~~~~2
单词数量发生变化:am~~~~~~~~2
单词数量发生变化:sure~~~~~~~~2
消息:i am so shuai----处理成功
消息:i am sure----处理成功
14794 [main] INFO backtype.storm.daemon.nimbus - Delaying event :remove for 30 secs for wordcount-topology-1-1524063976
14843 [main] INFO backtype.storm.daemon.nimbus - Updated wordcount-topology-1-1524063976 with status {:type :killed, :kill-time-secs 30}
14843 [main] INFO backtype.storm.daemon.nimbus - Shutting down master
14848 [ProcessThread(sid:0 cport:-1):] INFO org.apache.storm.zookeeper.server.PrepRequestProcessor - Processed session termination for sessionid: 0x162d94ab2e00001
14872 [main] INFO org.apache.storm.zookeeper.ZooKeeper - Session: 0x162d94ab2e00001 closed
14873 [main-EventThread] INFO org.apache.storm.zookeeper.ClientCnxn - EventThread shut down
14873 [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2000] INFO org.apache.storm.zookeeper.server.NIOServerCnxn - Closed socket connection for client /0:0:0:0:0:0:0:1:50710 which had sessionid 0x162d94ab2e00001
14873 [main] INFO backtype.storm.daemon.nimbus - Shut down master
14875 [ProcessThread(sid:0 cport:-1):] INFO org.apache.storm.zookeeper.server.PrepRequestProcessor - Processed session termination for sessionid: 0x162d94ab2e00003
14895 [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2000] INFO org.apache.storm.zookeeper.server.NIOServerCnxn - Closed socket connection for client /127.0.0.1:50716 which had sessionid 0x162d94ab2e00003
14895 [main] INFO org.apache.storm.zookeeper.ZooKeeper - Session: 0x162d94ab2e00003 closed
14895 [main-EventThread] INFO org.apache.storm.zookeeper.ClientCnxn - EventThread shut down
14897 [ProcessThread(sid:0 cport:-1):] INFO org.apache.storm.zookeeper.server.PrepRequestProcessor - Processed session termination for sessionid: 0x162d94ab2e00005
14928 [main] INFO org.apache.storm.zookeeper.ZooKeeper - Session: 0x162d94ab2e00005 closed
14928 [main-EventThread] INFO org.apache.storm.zookeeper.ClientCnxn - EventThread shut down
14929 [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2000] INFO org.apache.storm.zookeeper.server.NIOServerCnxn - Closed socket connection for client /0:0:0:0:0:0:0:1:50722 which had sessionid 0x162d94ab2e00005
14931 [main] INFO backtype.storm.daemon.supervisor - Shutting down 83b4eb09-c8a0-4932-aba0-0a8015dc4b50:a4988a3f-148a-4f74-ab48-7eb3f5a8ac86
14932 [main] INFO backtype.storm.process-simulator - Killing process b217cb78-eb90-41e5-a029-721cc42dfdaf
14932 [main] INFO backtype.storm.daemon.worker - Shutting down worker wordcount-topology-1-1524063976 83b4eb09-c8a0-4932-aba0-0a8015dc4b50 1024
14932 [main] INFO backtype.storm.daemon.worker - Shutting down receive thread
14933 [main] INFO backtype.storm.messaging.loader - Shutting down receiving-thread: [wordcount-topology-1-1524063976, 1024]
14933 [main] INFO backtype.storm.messaging.loader - Waiting for receiving-thread:[wordcount-topology-1-1524063976, 1024] to die
14934 [Thread-19-worker-receiver-thread-0] INFO backtype.storm.messaging.loader - Receiving-thread:[wordcount-topology-1-1524063976, 1024] received shutdown notice
14936 [main] INFO backtype.storm.messaging.loader - Shutdown receiving-thread: [wordcount-topology-1-1524063976, 1024]
14937 [main] INFO backtype.storm.daemon.worker - Shut down receive thread
14937 [main] INFO backtype.storm.daemon.worker - Terminating messaging context
14937 [main] INFO backtype.storm.daemon.worker - Shutting down executors
14938 [main] INFO backtype.storm.daemon.executor - Shutting down executor count-bolt:[2 2]
14939 [Thread-7-disruptor-executor[2 2]-send-queue] INFO backtype.storm.util - Async loop interrupted!
14939 [Thread-8-count-bolt] INFO backtype.storm.util - Async loop interrupted!
14940 [main] INFO backtype.storm.daemon.executor - Shut down executor count-bolt:[2 2]
14940 [main] INFO backtype.storm.daemon.executor - Shutting down executor report-bolt:[3 3]
14941 [Thread-9-disruptor-executor[3 3]-send-queue] INFO backtype.storm.util - Async loop interrupted!
14941 [Thread-10-report-bolt] INFO backtype.storm.util - Async loop interrupted!
----------统计结果-------------
am:2
are:1
do:2
i:2
like:2
me:2
not:1
shuai:1
so:1
sure:2
you:2
-------------------------------
14943 [main] INFO backtype.storm.daemon.executor - Shut down executor report-bolt:[3 3]
14944 [main] INFO backtype.storm.daemon.executor - Shutting down executor sentence-spout:[4 4]
14944 [Thread-12-sentence-spout] INFO backtype.storm.util - Async loop interrupted!
14944 [Thread-11-disruptor-executor[4 4]-send-queue] INFO backtype.storm.util - Async loop interrupted!
14945 [main] INFO backtype.storm.daemon.executor - Shut down executor sentence-spout:[4 4]
14945 [main] INFO backtype.storm.daemon.executor - Shutting down executor split-bolt:[5 5]
14946 [Thread-13-disruptor-executor[5 5]-send-queue] INFO backtype.storm.util - Async loop interrupted!
14946 [Thread-14-split-bolt] INFO backtype.storm.util - Async loop interrupted!
14947 [main] INFO backtype.storm.daemon.executor - Shut down executor split-bolt:[5 5]
14947 [main] INFO backtype.storm.daemon.executor - Shutting down executor __system:[-1 -1]
14947 [Thread-16-__system] INFO backtype.storm.util - Async loop interrupted!
14947 [Thread-15-disruptor-executor[-1 -1]-send-queue] INFO backtype.storm.util - Async loop interrupted!
14948 [main] INFO backtype.storm.daemon.executor - Shut down executor __system:[-1 -1]
14948 [main] INFO backtype.storm.daemon.executor - Shutting down executor __acker:[1 1]
14949 [Thread-18-__acker] INFO backtype.storm.util - Async loop interrupted!
14949 [Thread-17-disruptor-executor[1 1]-send-queue] INFO backtype.storm.util - Async loop interrupted!
14950 [main] INFO backtype.storm.daemon.executor - Shut down executor __acker:[1 1]
14950 [main] INFO backtype.storm.daemon.worker - Shut down executors
14950 [main] INFO backtype.storm.daemon.worker - Shutting down transfer thread
14951 [Thread-20-disruptor-worker-transfer-queue] INFO backtype.storm.util - Async loop interrupted!
14951 [main] INFO backtype.storm.daemon.worker - Shut down transfer thread
14952 [main] INFO backtype.storm.daemon.worker - Shutting down default resources
14952 [main] INFO backtype.storm.daemon.worker - Shut down default resources
14981 [main] INFO backtype.storm.daemon.worker - Disconnecting from storm cluster state context
14982 [ProcessThread(sid:0 cport:-1):] INFO org.apache.storm.zookeeper.server.PrepRequestProcessor - Processed session termination for sessionid: 0x162d94ab2e0000b
15006 [main] INFO org.apache.storm.zookeeper.ZooKeeper - Session: 0x162d94ab2e0000b closed
15006 [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2000] INFO org.apache.storm.zookeeper.server.NIOServerCnxn - Closed socket connection for client /127.0.0.1:50740 which had sessionid 0x162d94ab2e0000b
15006 [main] INFO backtype.storm.daemon.worker - Shut down worker wordcount-topology-1-1524063976 83b4eb09-c8a0-4932-aba0-0a8015dc4b50 1024
15006 [Thread-4-EventThread] INFO org.apache.storm.zookeeper.ClientCnxn - EventThread shut down
15034 [main] INFO backtype.storm.daemon.supervisor - Shut down 83b4eb09-c8a0-4932-aba0-0a8015dc4b50:a4988a3f-148a-4f74-ab48-7eb3f5a8ac86
15034 [main] INFO backtype.storm.daemon.supervisor - Shutting down supervisor 83b4eb09-c8a0-4932-aba0-0a8015dc4b50
15035 [Thread-3] INFO backtype.storm.event - Event manager interrupted
15035 [Thread-4] INFO backtype.storm.event - Event manager interrupted
15036 [ProcessThread(sid:0 cport:-1):] INFO org.apache.storm.zookeeper.server.PrepRequestProcessor - Processed session termination for sessionid: 0x162d94ab2e00007
15087 [main] INFO org.apache.storm.zookeeper.ZooKeeper - Session: 0x162d94ab2e00007 closed
15087 [main-EventThread] INFO org.apache.storm.zookeeper.ClientCnxn - EventThread shut down
15087 [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2000] INFO org.apache.storm.zookeeper.server.NIOServerCnxn - Closed socket connection for client /127.0.0.1:50728 which had sessionid 0x162d94ab2e00007
15089 [main] INFO backtype.storm.daemon.supervisor - Shutting down supervisor d0232aba-a29a-4905-a3f5-f26d464a295c
15089 [Thread-5] INFO backtype.storm.event - Event manager interrupted
15090 [Thread-6] INFO backtype.storm.event - Event manager interrupted
15092 [ProcessThread(sid:0 cport:-1):] INFO org.apache.storm.zookeeper.server.PrepRequestProcessor - Processed session termination for sessionid: 0x162d94ab2e00009
15117 [main] INFO org.apache.storm.zookeeper.ZooKeeper - Session: 0x162d94ab2e00009 closed
15117 [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2000] INFO org.apache.storm.zookeeper.server.NIOServerCnxn - Closed socket connection for client /127.0.0.1:50734 which had sessionid 0x162d94ab2e00009
15118 [main-EventThread] INFO org.apache.storm.zookeeper.ClientCnxn - EventThread shut down
15120 [main] INFO backtype.storm.testing - Shutting down in process zookeeper
15123 [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2000] INFO org.apache.storm.zookeeper.server.NIOServerCnxnFactory - NIOServerCnxn factory exited run method
15124 [main] INFO org.apache.storm.zookeeper.server.ZooKeeperServer - shutting down
15124 [main] INFO org.apache.storm.zookeeper.server.SessionTrackerImpl - Shutting down
15124 [main] INFO org.apache.storm.zookeeper.server.PrepRequestProcessor - Shutting down
15125 [main] INFO org.apache.storm.zookeeper.server.SyncRequestProcessor - Shutting down
15126 [ProcessThread(sid:0 cport:-1):] INFO org.apache.storm.zookeeper.server.PrepRequestProcessor - PrepRequestProcessor exited loop!
15126 [SyncThread:0] INFO org.apache.storm.zookeeper.server.SyncRequestProcessor - SyncRequestProcessor exited!
15127 [main] INFO org.apache.storm.zookeeper.server.FinalRequestProcessor - shutdown of request processor complete
15128 [main] INFO backtype.storm.testing - Done shutting down in process zookeeper
15128 [main] INFO backtype.storm.testing - Deleting temporary path C:\Users\ADMINI~1\AppData\Local\Temp\0ffaf4ec-af92-4710-b9d1-32ffe4ff2921
15145 [main] INFO backtype.storm.testing - Deleting temporary path C:\Users\ADMINI~1\AppData\Local\Temp\8907dc4f-ca9a-4f7a-afa0-3999175e6743
15149 [main] INFO backtype.storm.testing - Unable to delete file: C:\Users\ADMINI~1\AppData\Local\Temp\8907dc4f-ca9a-4f7a-afa0-3999175e6743\version-2\log.1
15149 [main] INFO backtype.storm.testing - Deleting temporary path C:\Users\ADMINI~1\AppData\Local\Temp\c901ad6c-67e7-45f3-9f07-1ccb2fbb1937
15175 [main] INFO backtype.storm.testing - Deleting temporary path C:\Users\ADMINI~1\AppData\Local\Temp\2d7d0d53-eec3-428e-951e-5e7477796fea
16090 [SessionTracker] INFO org.apache.storm.zookeeper.server.SessionTrackerImpl - SessionTrackerImpl exited loop!