流式计算框架 Storm

概述

Storm是一个流式计算框架,数据源源不断的产生,源源不断的收集,源源不断的计算。(一条数据一条数据的处理)

架构

Nimbus:负责资源分配和任务调度。

Supervisor:负责接受nimbus分配的任务,启动和停止属于自己管理的worker进程。

Worker:运行具体处理组件逻辑的进程。

Task:worker中每一个spout/bolt的线程称为一个task. 在storm0.8之后,task不再与物理线程对应,同一个spout/bolt的task可能会共享一个物理线程,该线程称为executor。

storm编程模型

Topology:Storm中运行的一个实时应用程序,因为各个组件间的消息流动形成逻辑上的一个拓扑结构。

Spout:在一个topology中产生源数据流的组件。通常情况下spout会从外部数据源中读取数据,然后转换为topology内部的源数据。Spout是一个主动的角色,其接口中有个nextTuple()函数,storm框架会不停地调用此函数,用户只要在其中生成源数据即可。

Bolt:在一个topology中接受数据然后执行处理的组件。Bolt可以执行过滤、函数操作、合并、写数据库等任何操作。Bolt是一个被动的角色,其接口中有个execute(Tuple input)函数,在接受到消息后会调用此函数,用户可以在其中执行自己想要的操作。

Tuple:一次消息传递的基本单元。本来应该是一个key-value的map,但是由于各个组件间传递的tuple的字段名称已经事先定义好,所以tuple中只要按序填入各个value就行了,所以就是一个value list.

Stream:源源不断传递的tuple就组成了stream。

案列

import org.apache.storm.spout.SpoutOutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.base.BaseRichSpout;
import org.apache.storm.tuple.Fields;
import org.apache.storm.utils.BufferInputStream;

import java.io.*;
import java.util.Arrays;
import java.util.Map;

public class ReadFileSpout extends BaseRichSpout {
private SpoutOutputCollector collector;
private BufferedReader in ;
/*
这个open方法, 会在对象被初始化的时候, 会执行, 一般只会执行一次

    Map :  设置和获取是storm的配置信息, 这个一般不使用

    TopologyContext :  这个任务的全局对象, 这个一般不使用

    SpoutOutputCollector:  帮助将数据从上游发送到下游  (重要的)
 */
@Override
public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
    this.collector = collector;

    try {

        in = new BufferedReader(new FileReader("F:\\words.txt"));
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

}

/*
*   nextTuple 方法, 一旦将任务提交给是storm框架或者集群, storm就会无休止调用这个nextTuple
* */
@Override
public void nextTuple() {
    try {
        String line = in.readLine();

        if(line !=null && !"".equals(line)){
            //如果有数据, 向下游发送数据

            collector.emit(Arrays.asList(line));
        }

    } catch (IOException e) {
        e.printStackTrace();
    }
}

/*
*   declareOutputFields : 是用来定义从上游发送到下游数据的字段名的
* */
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
    declarer.declare(new Fields("line"));
}

}

import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.base.BaseRichBolt;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Tuple;

import java.util.Arrays;
import java.util.Map;

public class SplitBolt extends BaseRichBolt {
private OutputCollector collector;
@Override
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
this.collector = collector;
}
/*
* 只要上游有数据发送给下游, 下游的execute就会被执行
* */
@Override
public void execute(Tuple tuple) {
//1. 从tuple中获取上游发送的数据
String line = tuple.getStringByField(“line”);

    //2. 执行切割操作
    String[] words = line.split(" ");
    //3. 遍历数组, 获取到一个个的单词, 将一个个的单词发送给下游
    for (String word : words) {
        collector.emit(Arrays.asList(word,1));
    }
}

@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
    declarer.declare(new Fields("word","count"));
}

}

import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.base.BaseRichBolt;
import org.apache.storm.tuple.Tuple;

import java.util.HashMap;
import java.util.Map;
// 统计计算
public class CountBolt extends BaseRichBolt {
private OutputCollector collector;
private Map<String,Integer> map = new HashMap<>();
@Override
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
this.collector = collector;
}

@Override
public void execute(Tuple tuple) {
    //1. 接收上游的数据
    String word = tuple.getStringByField("word");
    Integer count = tuple.getIntegerByField("count");

    //2. 统计计算
    Integer num = map.get(word);
    if(num == null || num == 0 ){

        map.put(word,count);
    }else {
        num ++;
        map.put(word,num);
    }

    //3. 打印统计的结果
    System.out.println(map);
}

@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {

}

}

import org.apache.storm.Config;
import org.apache.storm.LocalCluster;
import org.apache.storm.generated.StormTopology;
import org.apache.storm.topology.TopologyBuilder;

// 构建整个拓扑关系
public class TopologyMain {

public static void main(String[] args) {
    // 1. 创建拓扑构建器
    TopologyBuilder builder = new TopologyBuilder();

    //2. 构建各个程序之前关系信息

    builder.setSpout("readFileSpout",new ReadFileSpout());

    builder.setBolt("splitBolt",new SplitBolt()).shuffleGrouping("readFileSpout");

    builder.setBolt("countBolt",new CountBolt()).shuffleGrouping("splitBolt") ;

    //3. 通过构建器, 生成一个 拓扑关系对象
    StormTopology topology = builder.createTopology();  // 任务


    //4.  执行任务 : 一种本地运行, 一种 集群运行

    LocalCluster  localCluster = new LocalCluster();
    // 参数1: 任务的名称 , 参数2: 任务运行的配置信息  参数3:  任务对象
    Config conf = new Config();
    localCluster.submitTopology("wordCount",conf,topology);
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值