一、关于流式计算:
①离线计算:批量获取数据、批量传输数据、周期性批量计算数据、数据展示
代表技术:Sqoop批量导入数据、HDFS批量存储数据、MapReduce批量计算数据、Hive批量计算数据、***任务调度
②流式计算:数据实时产生、数据实时传输、数据实时计算、实时展示
代表技术:Flume实时获取数据、Kafka/metaq实时数据存储、Storm/JStorm实时数据计算、Redis实时结果缓存、持久化存储(mysql)。
一句话总结:将源源不断产生的数据实时收集并实时计算,尽可能快的得到计算结果。离线计算与实时计算的区别--最大的区别:实时收集、实时计算、实时展示
Storm用来实时计算源源不断产生的数据,如同流水线生产。
对于storm来说计算特点:低延迟、高可用、分布式、可扩展、数据不丢失。提供简单容易理解的接口,便于开发。
Flume实时采集,低延迟
Kafka消息队列,低延迟
Storm实时计算,低延迟
Redis实时存储,低延迟
Storm与Hadoop是相对的。
Storm用于实时计算,Hadoop用于离线计算。
Storm处理的数据保存在内存中,源源不断;Hadoop处理的数据保存在文件系统中,一批一批。
Storm的数据通过网络传输进来;Hadoop的数据保存在磁盘中。
二者编程模型相似!
Hadoop:
Job:任务名称
JobTracker:项目经理
TaskTracker:开发组长、产品经理
Child:负责开发的人员
Mapper/Reduce:开发人员中的两种角色,一种是服务器开发、一种是客户端开发
Storm:核心组件
Topology:任务名称
Nimbus:项目经理------负责资源分配和任务调度。
Supervisor:开组长、产品经理-----负责接受nimbus分配的任务,启动和停止属于自己管理的worker进程。---通过配置文件设置当前supervisor上启动多少个worker。
Worker:开人员----运行具体处理组件逻辑的进程。Worker运行的任务类型只有两种,一种是Spout任务,一种是Bolt任务。
Spout/Bolt:开人员中的两种角色,一种是服务器开发、一种是客户端开发
Task:worker中每一个spout/bolt的线程称为一个task. 在storm0.8之后,task不再与物理线程对应,不同spout/bolt的task可能会共享一个物理线程,该线程称为executor。
阿里妈妈-用户画像:实时计算用户的兴趣数据
为了更加精准投放广告,阿里妈妈后台计算引擎需要维护每个用户的兴趣点(理想状态是,你对什么感兴趣,就向你投放哪类广告)。用户兴趣主要基于用户的历史行为、用户的实时查询、用户的实时点击、用户的地理信息而得,其中实时查询、实时点击等用户行为都是实时数据。考虑到系统的实时性,阿里妈妈使用Storm维护用户兴趣数据,并在此基础上进行受众定向的广告投放。
Storm编程模型
Topology:Storm中运行的一个实时应用程序的名称。(拓扑)类似MR
Spout:在一个topology中获取源数据流的组件。类似Map
通常情况下spout会从外部数据源中读取数据,然后转换为topology内部的源数据。
Bolt:接受数据然后执行处理的组件,用户可以在其中执行自己想要的操作。类似Reduce
Tuple:一次消息传递的基本单元,理解为一组消息就是一个Tuple。
Stream:表示数据的流向。
流式计算一般架构图 flume用来获取数据 Kafka用来临时保存数据。 Strom用来计算数据 Redis内存数据库,用来保存数据
二、storm启动(后台启动服务)
先在每台机器上启动zookeeper:zkServer.sh start
①server----->: nohup ./storm nimbus & 主节点启动nimbus
②server,server02.server03----->: nohup ./storm supervisor & 三个子节点启动 supervisor
③server----->: nohup ./storm ui & 主节点启动web UI界面 http://server:8080 打开ui查看
三、关于eclipse下操作storm的细节
安装maven,配置maven的安装路径,设置库。
将storm(linux下安装的)解压到本地,然后将lib下的库添加到maven项目中
备注:
备注:storm也分为两种工作模式
本地工作模式:在IDE中运行,主要测试代码功能
集群工作模式:完成工作
本地模式时,调试时将scope<>注释掉;等打包部署时再打开!
切换时,scope,修改,再就是修改提交的对象
//集群模式下运行
StormSubmitter.submitTopology("mywordcount",config,topologyBuilder.createTopology());
//本地运行时设置
LocalCluster localCluster = new LocalCluster();
localCluster.submitTopology("mywordcount",config,topologyBuilder.createTopology());
总体分四个类:①Spout:
初始化方法open():
//初始化方法
public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
this.collector = collector;
}
//storm 框架在 while(true) 调用nextTuple方法
public void nextTuple() {
collector.emit(new Values("i am lilei love hanmeimei"));
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("love"));
}
初始化方法prepare()
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
this.collector = collector;
}
// 被storm框架 while(true) 循环调用 传入参数tuple
public void execute(Tuple input) {
String line = input.getString(0);
String[] arrWords = line.split(" ");
for (String word:arrWords){
collector.emit(new Values(word,1));
}
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word","num"));
}
OutputCollector collector;
Map<String, Integer> map = new HashMap<String, Integer>();
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
this.collector = collector;
}
public void execute(Tuple input) {
String word = input.getString(0);
Integer num = input.getInteger(1);
System.out.println(Thread.currentThread().getId() + " word:"+word);
if (map.containsKey(word)){
Integer count = map.get(word);
map.put(word,count + num);
}else {
map.put(word,num);
}
System.out.println("count:"+map);
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
//不輸出
}
④main类
创建拓扑,配置接连进行的三个类方法
public static void main(String[] args) throws AlreadyAliveException, InvalidTopologyException {
//1、准备一个TopologyBuilder
TopologyBuilder topologyBuilder = new TopologyBuilder();
topologyBuilder.setSpout("mySpout",new MySpout(),2);
topologyBuilder.setBolt("mybolt1",new MySplitBolt(),2).shuffleGrouping("mySpout");
topologyBuilder.setBolt("mybolt2",new MyCountBolt(),4).fieldsGrouping("mybolt1", new Fields("word"));
- /**
* i
* am
* lilei
* love
* hanmeimei
*/
- //2、创建一个configuration,用来指定当前topology 需要的worker的数量
Config config = new Config();
config.setNumWorkers(2);
//3、提交任务 -----两种模式 本地模式和集群模式
StormSubmitter.submitTopology("mywordcount",config,topologyBuilder.createTopology());
// LocalCluster localCluster = new LocalCluster();
// localCluster.submitTopology("mywordcount",config,topologyBuilder.createTopology());
}
备注:
四个类,main类主要完成,配置运行模式,配置spout,bolt的模式;
Spout()通过设定nextTuple()方法,来确定输入的数据源;---Spout
splitBolt()设定execute()方法来循环执行数据的切片任务;---Bolt
countBolt()也是设定execute()方法来循环查询单词统计次数。---Bolt