java工程实现简单Storm--详细注解

设计思想

在Storm中也有对流(Stream)的抽象,流是一个不间断的、无界的连续TupleTuple是包含一个或多个键值对的集合。

Storm认为每个流都有一个Stream源,也就是原始元组的源头,所以它将这个源头抽象为Spout(水龙头),Spout可能连接Twitter API并不断发出推文(Tweet),也可能从某个队列中不断读取队列元素并装配为Tuple发射。

有了源头即Spout也就是有了流,同样的思想,Twitter将流的中间状态转换抽象为Bolt,Bolt可以消费任意数量的输入流,只要将流方向导向该Bolt,同时它也可以发送新的流给其他Bolt使用,这样一来,只要打开特定的Spout(管口),再将Spout中流出的Tuple导向特定的Bolt,由Bolt处理导入的流后再导向其他Bolt或者目的地。

假设Spout就是一个一个的水龙头,并且每个水龙头里流出的水是不同的,想获得哪种水就拧开哪个水龙头,然后使用管道将水龙头的水导向到一个水处理器(Bolt),水处理器处理后使用管道导向另一个处理器或者存入容器中。如下图所以Spout、Tuple和Bolt之间的关系和流程。

图解1

图解2

Java工程建立一个Storm

Spout--负责发送数据(数据源的生产者)

Bolt--建立节点处理源流出来的数据(运算)

Topology--提交拓扑到Storm集群执行(拓扑)

 

数据源--NumberSpout.java


import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.Map;
import java.util.Random;

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;
//开发Spout组件的方式---extends
public class NumberSpout extends BaseRichSpout {
	private SpoutOutputCollector collector;
	@Override
	public void nextTuple() {//此方法用于产生数据源,而且此方法会不断地被调用,直到整个拓扑被终止
		int number=new Random().nextInt(100);//每调用一次就会产生一个随机数
		SimpleDateFormat time = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
		String date = time.format(new java.util.Date());
		Values value=new Values(number,date);//把数据封装到Tuple的value对象中,value对象的参数是可变参数(个数不限,类型不限--object)
		collector.emit(value);//通过发射器将tuple发送给下游
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	@Override
	//主键的初始化方法,且只会被调用一次,一般做资源的初始化
	public void open(Map arg0, TopologyContext arg1, SpoutOutputCollector collector) {
		this.collector=collector;
	}
	@Override
	public void declareOutputFields(OutputFieldsDeclarer declarer) {//声明key
		//声明tuple的key字段--tuple和key一一对应,且数量保持一致
		declarer.declare(new Fields("number","date"));
	}

}

数据处--PrintBolt.java

import java.sql.Date;
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;

public class PrintBolt extends BaseRichBolt {
	private OutputCollector collector;//创建bolt组建的tuple发射器,用于向下游发射tuple
	@Override
	public void execute(Tuple input) {
		int number=input.getIntegerByField("number");//元祖是一种key-v结构,通过key来去value值
		String date=input.getStringByField("date");
		System.out.println(number+"...."+date);
		System.out.println(System.currentTimeMillis());//添加一个时间戳
	}
	@Override
	public void prepare(Map arg0, TopologyContext arg1, OutputCollector collector) {
		//此方法是bolt组件的初始化方法--最常用的是初始化发生器
		this.collector=collector;
	}
	@Override
	public void declareOutputFields(OutputFieldsDeclarer arg0) {
		// TODO Auto-generated method stub
	}
}

提交拓扑--NumberTopology.java

import backtype.storm.Config;
import backtype.storm.LocalCluster;
import backtype.storm.generated.StormTopology;
import backtype.storm.topology.TopologyBuilder;
import numberberrouter.Number;

public class NumberTopology {

	public static void main(String[] args) {
		Config conf=new Config();
		Number spout=new Number();
		PrintBolt printBolt=new PrintBolt();
		//创建拓扑构建者,用于绑定各组件的上下游关系
		TopologyBuilder builder=new TopologyBuilder();
		//绑定数据源,组件标识id  组件对象
		builder.setSpout("number_spout", spout);
		//绑定Bolt并制定上游组件是数据源
		builder.setBolt("print_bolt", printBolt).shuffleGrouping("number_spout");
		//生成拓扑对象--即一个job任务
		StormTopology topology=builder.createTopology();
		//创建本地测试对象
		LocalCluster cluster=new LocalCluster();
		//提交拓扑运行
		cluster.submitTopology("number_topolopy", conf, topology);
	}
}

运行结果:

82....2019-01-03 19:57:24
1546516644994
4....2019-01-03 19:57:27
1546516647994

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值