Storm单词计数案例的编写

1.拓扑程序中的基本概念

在这里插入图片描述

  1. Stream:流数据,持续不断产生的数据流。
  2. Spout:数据源,类似于kafka Streaming中的Source组件,负责从外部的存储系统获取一条条记录,并且会将这些记录封装为一个Tuple(元组)对象。Spout将封装好的Tuple发送给下游的Bolt组件,进行加工处理。 常用Spout类型IRichSpout(最多一次处理),IBaseSpout(最少一次处理)。
  3. Bolt: 处理器,对接口到的Tuple进行加工处理(产生新的Tuple),继续将新产生的Tuple发射交由下游的Bolt进行处理,常用Bolt类型:IRichBolt,IBaseBolt。
  4. Tuple: Storm流数据中的一条记录,Tuple本质是一个可以存放任何类型的List集合Tuple=List(1,true,“zs”), Tuple只能赋值一次(read only)。

2.应用开发

整体结构分析
在这里插入图片描述

2.1 引入相关依赖

<dependency>
    <groupId>org.apache.storm</groupId>
    <artifactId>storm-core</artifactId>
    <version>2.0.0</version>
    <!-- 依赖的作用范围 scope依靠外部的容器或者应用提供 -->
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.apache.storm</groupId>
    <artifactId>storm-client</artifactId>
    <version>2.0.0</version>
    <scope>provided</scope>
</dependency>

2.2 编写Spout

package quickstart;

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.tuple.Values;
import org.apache.storm.utils.Utils;

import java.util.Map;
import java.util.Random;

/**
 * 负责生产一行行的英文短语
 */
public class LinesSpout extends BaseRichSpout {

    // 模拟数据 英文短语
    private String[] lines = null;

    private SpoutOutputCollector collector = null;
    /**
     * 初始化方法
     * @param conf
     * @param context
     * @param collector
     */
    public void open(Map<String, Object> conf, TopologyContext context, SpoutOutputCollector collector) {
        lines = new String[]{"Hello Storm","Hello Kafka","Hello Spark"};
        this.collector = collector;
    }

    /**
     * 创建元组方法
     */
    public void nextTuple() {
        // 每隔5秒 新产生一个tuple 并且将它发送给下游的处理器
        Utils.sleep(5000);
        // 随机数:0 - 2
        int num = new Random().nextInt(lines.length);
        // 随机获取一行英文短语
        String line = lines[num];
        // 将随机产生的数据封装为1个Tuple元组
        // 将封装好的tuple发送给下游的处理器bolt
        collector.emit(new Values(line));
    }

    /**
     * 说明输出元组信息
     * @param declarer
     */
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("line"));
    }
}

2.3 编写LineSplitBolt

package quickstart;

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 org.apache.storm.tuple.Values;

import java.util.Map;

/**
 * 流数据的处理器
 *     line ---> word
 */
public class LineSplitBolt extends BaseRichBolt {

    private OutputCollector collector = null;
    /**
     * 准备方法
     * @param topoConf
     * @param context
     * @param collector
     */
    public void prepare(Map<String, Object> topoConf, TopologyContext context, OutputCollector collector) {
        this.collector = collector;
    }

    /**
     * 执行方法
     * @param input
     */
    public void execute(Tuple input) {
        String line = input.getStringByField("line");
        String[] words = line.split(" ");
        for (String word : words) {
            // 新创建的元组  交给下游的处理器 统计和计算
            collector.emit(new Values(word));
        }
    }

    /**
     *
     * @param declarer
     */
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("word"));
    }
}

2.4 编写WordCountBolt

package quickstart;

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;

/**
 * 统计单词出现的次数
 * word --> word count
 */
public class WordCountBolt extends BaseRichBolt {

    private HashMap<String, Long> wordCount = null;

    public void prepare(Map<String, Object> topoConf, TopologyContext context, OutputCollector collector) {
        wordCount = new HashMap<String, Long>();
    }

    /**
     * 单词计数案例:
     *      wordcountBolt最终的处理器
     * @param input
     */
    public void execute(Tuple input) {
        String word = input.getStringByField("word");
        // 累计单词出现次数(计算状态)
        Long num = wordCount.getOrDefault(word, 0L);
        num++;
        wordCount.put(word, num);
        System.out.println(word + "\t" + num);
    }

    public void declareOutputFields(OutputFieldsDeclarer declarer) {

    }
}

2.5 初始化类WordCountApplication

package quickstart;

import org.apache.storm.Config;
import org.apache.storm.StormSubmitter;
import org.apache.storm.generated.AlreadyAliveException;
import org.apache.storm.generated.AuthorizationException;
import org.apache.storm.generated.InvalidTopologyException;
import org.apache.storm.topology.TopologyBuilder;
import org.apache.storm.tuple.Fields;

/**
 * 编制拓扑应用程序
 */
public class WordCountApplication {

    public static void main(String[] args) throws InvalidTopologyException, AuthorizationException, AlreadyAliveException {
        //1. 构建topology的DAG(有向无环图)
        TopologyBuilder builder = new TopologyBuilder();
        builder.setSpout("s1",new LinesSpout());
        // 参数三:设置计算单元并行度 默认1
        builder.setBolt("b1",new LineSplitBolt(),2)
                // 将spout生产的元组tuple均等分配给b1组件的多个并行任务
                .shuffleGrouping("s1");
        builder.setBolt("b2",new WordCountBolt(),3)
                // 将指定的field相同的数据 归为1组
                .fieldsGrouping("b1",new Fields("word"));

        //2. 将topology提交运行
        // 参数1:拓扑任务名
        Config config = new Config();
        // 当前拓扑运行时 需要占用两个槽位(2个worker进程)
        config.setNumWorkers(2);
        config.setNumAckers(0); // storm可靠性处理相关
        StormSubmitter.submitTopology("storm-wordcount",config,builder.createTopology());
    }
}

2.6 提交任务

# 将storm的拓扑应用 打包,并上传到storm集群,通过以下命令提交任务
[root@node1 apache-storm-2.0.0]# storm jar /root/storm-demo-1.0-SNAPSHOT.jar quickstart.WordCountApplication

2.7 查看拓扑任务的状态

[root@node1 apache-storm-2.0.0]# storm list

在这里插入图片描述

2.8 Strom UI 的拓扑摘要详解

在这里插入图片描述

2.9 结束拓扑任务

主节点上进行操作

[root@node1 apache-storm-2.0.0]# storm kill storm-wordcount(拓扑任务的名字) 

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值