package com.uplooking.bigdata.storm.test;
import org.apache.storm.Config;
import org.apache.storm.Constants;
import org.apache.storm.LocalCluster;
import org.apache.storm.generated.StormTopology;
import org.apache.storm.spout.SpoutOutputCollector;
import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.TopologyBuilder;
import org.apache.storm.topology.base.BaseRichBolt;
import org.apache.storm.topology.base.BaseRichSpout;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Tuple;
import org.apache.storm.tuple.Values;
import java.util.HashMap;
import java.util.Map;
/**
* 定时调度
* 有两种处理方式
* 全局处理
* 一般我们都住不需要进行全局延时,因为这样出产生大量的系统级别的数据,操作效率相对低下
* 在main()中启动topology的时候,在conf中进行参数设置
* conf.put(Config.TOPOLOGY_TICK_TUPLE_FREQ_SECS, 10);
* 意思是说每隔10s向该topology中的所有bolt都发送一个系统级别的tuple
局部进行处理
一般都只需要在最后一个落地的bolt设置延时处理
在特定的bolt,中进行上述的设置,需要覆盖其中的方法getComponentConfiguration()
在该方法中做上述全局处理一样的设置即可
*/
public class TimerSchedulerSumTopology {
/**
* 当前spout用于接收数据源的数据
*/
static class SumNumSpout extends BaseRichSpout {
private Map conf;
private TopologyContext context;
private SpoutOutputCollector collector;
/**
* 这是一个生命周期方法,一个SumNumSpout实例只运行一次,主要完成初始化的参数设置
* @param conf ---->storm程序以及storm集群相关的配置信息
* @param context ---->整个Topology上下文对象,可以通过该context获得相关topology应用属性
* @param collector ---->主要用于收集数据,并将数据发射到下一个阶段
*/
public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
this.conf = conf;
this.context = context;
this.collector = collector;
}
/*
storm程序只要nextTuple方法,完成数据采集,处理,发射到下游bolt
*/
int num = 0;
public void nextTuple() {
// num++;//数据自增
// Values
System.out.println("spout产生的数据:" + num);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// collector.emit(new Values(num++));//使用collector发射数据
collector.emit(new Values(num++), System.currentTimeMillis());
}
//是对发射到下游bolt中的数据的一个说明
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("num"));
}
}
/**
* 对接收到spout中的数据的处理逻辑
*/
static class SumNumBolt extends BaseRichBolt {
private Map conf;
private TopologyContext context;
private OutputCollector collector;
public void prepare(Map conf, TopologyContext context, OutputCollector collector) {
this.conf = conf;
this.context = context;
this.collector = collector;
}
int sum = 0;
//这里面对接收上游数据的一个处理
public void execute(Tuple tuple) {
//每隔10s中进行一次数据的落地操作
if(tuple.getSourceComponent().equalsIgnoreCase(Constants.SYSTEM_COMPONENT_ID)) {
System.out.println("当前时间:" + (System.currentTimeMillis() / 1000)+ "bolt累加之后的结果值:" + sum );
}else {
int num = tuple.getIntegerByField("num");
sum += num;
}
}
//类似于spout中的declareOutputFields方法,如果还有下游bolt操作,那需要在这里面进行一个说明
//如果没有下面bolt操作,这个方法就可以不用进行任何操作
public void declareOutputFields(OutputFieldsDeclarer declarer) {
}
//设置局部定时配置,每隔10s向当前bolt发送一个系统级别的tuple
@Override
public Map<String, Object> getComponentConfiguration() {
Map<String, Object> conf = new HashMap<String, Object>();
conf.put(Config.TOPOLOGY_TICK_TUPLE_FREQ_SECS, 10);
return conf;
}
}
public static void main(String[] args) {
//主要就是用来组织spout和bolt成为一个Topology拓扑,提交到集群
//构建Topology是通过TopologyBuilder来进行设置
TopologyBuilder topologyBuilder = new TopologyBuilder();
//set spout
//spout_id-->
String spoutID = "sumNumSpout_id";
topologyBuilder.setSpout(spoutID, new SumNumSpout());
//设置bolt
//.shuffleGrouping(spoutID)--->设置数据来源
String boltID = "sumNumBolt_id";
topologyBuilder.setBolt(boltID, new SumNumBolt()).shuffleGrouping(spoutID);
//产生topology
StormTopology stormTopology = topologyBuilder.createTopology();
//因为咱们本地运行,所以使用LocalCluster就可以
LocalCluster cluster = new LocalCluster();
/**
* topologyName
* Map---->configuration
* StormTopology
*/
String topologyName = TimerSchedulerSumTopology.class.getSimpleName();
Config config = new Config();
// config.setNumAckers(0);
cluster.submitTopology(topologyName, config, stormTopology);
}
}
import org.apache.storm.Config;
import org.apache.storm.Constants;
import org.apache.storm.LocalCluster;
import org.apache.storm.generated.StormTopology;
import org.apache.storm.spout.SpoutOutputCollector;
import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.TopologyBuilder;
import org.apache.storm.topology.base.BaseRichBolt;
import org.apache.storm.topology.base.BaseRichSpout;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Tuple;
import org.apache.storm.tuple.Values;
import java.util.HashMap;
import java.util.Map;
/**
* 定时调度
* 有两种处理方式
* 全局处理
* 一般我们都住不需要进行全局延时,因为这样出产生大量的系统级别的数据,操作效率相对低下
* 在main()中启动topology的时候,在conf中进行参数设置
* conf.put(Config.TOPOLOGY_TICK_TUPLE_FREQ_SECS, 10);
* 意思是说每隔10s向该topology中的所有bolt都发送一个系统级别的tuple
局部进行处理
一般都只需要在最后一个落地的bolt设置延时处理
在特定的bolt,中进行上述的设置,需要覆盖其中的方法getComponentConfiguration()
在该方法中做上述全局处理一样的设置即可
*/
public class TimerSchedulerSumTopology {
/**
* 当前spout用于接收数据源的数据
*/
static class SumNumSpout extends BaseRichSpout {
private Map conf;
private TopologyContext context;
private SpoutOutputCollector collector;
/**
* 这是一个生命周期方法,一个SumNumSpout实例只运行一次,主要完成初始化的参数设置
* @param conf ---->storm程序以及storm集群相关的配置信息
* @param context ---->整个Topology上下文对象,可以通过该context获得相关topology应用属性
* @param collector ---->主要用于收集数据,并将数据发射到下一个阶段
*/
public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
this.conf = conf;
this.context = context;
this.collector = collector;
}
/*
storm程序只要nextTuple方法,完成数据采集,处理,发射到下游bolt
*/
int num = 0;
public void nextTuple() {
// num++;//数据自增
// Values
System.out.println("spout产生的数据:" + num);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// collector.emit(new Values(num++));//使用collector发射数据
collector.emit(new Values(num++), System.currentTimeMillis());
}
//是对发射到下游bolt中的数据的一个说明
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("num"));
}
}
/**
* 对接收到spout中的数据的处理逻辑
*/
static class SumNumBolt extends BaseRichBolt {
private Map conf;
private TopologyContext context;
private OutputCollector collector;
public void prepare(Map conf, TopologyContext context, OutputCollector collector) {
this.conf = conf;
this.context = context;
this.collector = collector;
}
int sum = 0;
//这里面对接收上游数据的一个处理
public void execute(Tuple tuple) {
//每隔10s中进行一次数据的落地操作
if(tuple.getSourceComponent().equalsIgnoreCase(Constants.SYSTEM_COMPONENT_ID)) {
System.out.println("当前时间:" + (System.currentTimeMillis() / 1000)+ "bolt累加之后的结果值:" + sum );
}else {
int num = tuple.getIntegerByField("num");
sum += num;
}
}
//类似于spout中的declareOutputFields方法,如果还有下游bolt操作,那需要在这里面进行一个说明
//如果没有下面bolt操作,这个方法就可以不用进行任何操作
public void declareOutputFields(OutputFieldsDeclarer declarer) {
}
//设置局部定时配置,每隔10s向当前bolt发送一个系统级别的tuple
@Override
public Map<String, Object> getComponentConfiguration() {
Map<String, Object> conf = new HashMap<String, Object>();
conf.put(Config.TOPOLOGY_TICK_TUPLE_FREQ_SECS, 10);
return conf;
}
}
public static void main(String[] args) {
//主要就是用来组织spout和bolt成为一个Topology拓扑,提交到集群
//构建Topology是通过TopologyBuilder来进行设置
TopologyBuilder topologyBuilder = new TopologyBuilder();
//set spout
//spout_id-->
String spoutID = "sumNumSpout_id";
topologyBuilder.setSpout(spoutID, new SumNumSpout());
//设置bolt
//.shuffleGrouping(spoutID)--->设置数据来源
String boltID = "sumNumBolt_id";
topologyBuilder.setBolt(boltID, new SumNumBolt()).shuffleGrouping(spoutID);
//产生topology
StormTopology stormTopology = topologyBuilder.createTopology();
//因为咱们本地运行,所以使用LocalCluster就可以
LocalCluster cluster = new LocalCluster();
/**
* topologyName
* Map---->configuration
* StormTopology
*/
String topologyName = TimerSchedulerSumTopology.class.getSimpleName();
Config config = new Config();
// config.setNumAckers(0);
cluster.submitTopology(topologyName, config, stormTopology);
}
}