storm

留给刚开始学习的自己一点笔记

常用命令行操作

  • bin/storm nimous &     后台启动nimous
  • bin/storm supervisor &     后台启动supervisor
  • bin/storm ui &    后台启动ui(默认端口号8080)
  • bin/storm logviewer &    提供一个web接口查看storm日志文件
  • bin/storm list     列出正在运行的拓扑及其状态
  • bin/storm jar 【jar路径】 【拓扑包名。拓扑类名】 【拓扑名称】   启动storm程序
  • bin/storm kill topology-name [-w wait-time-secs]     杀死名为topology-name的拓扑,-w等待多久后杀死
  • bin/storm active topology-name     激活指定的拓扑spout
  • bin/storm deactive topology-name     禁用指定的拓扑spout
  • bin/storm help 打印一条帮助消息或者可用命令列表

storm和hadoop的区别

  1. storm用于实时计算;hadoop用于离线计算
  2. storm处理的数据保存在内存中,源源不断;hadoop保存在文件系统中,一批一批处理
  3. storm的数据通过网络传输进来;hadoop的数据保存在磁盘中
  4. storm与hadoop的编程模型相似
 stormhadoop
角色NimbusJobTracker
 SupervisorTaskTracker
 WokerChild
应用名称TopologyJob
编程接口Spout / BoltMapper / Reducer

storm的编程模型

在这里插入图片描述
Tuple:Tuple是Storm中的主要数据结构。它是有序元素的列表。默认情况下,Tuple支持所有数据类型。通常,它被建模为一组逗号分隔的值,并传递到Storm集群。

Stream:流是元组的无序序列。

Spouts :流的源。通常,Storm从原始数据源(如Twitter Streaming API,Apache Kafka队列,Kestrel队列等)接受输入数据。否则,您可以编写spouts以从数据源读取数据。“ISpout”是实现spouts的核心接口,一些特定的接口是IRichSpout,BaseRichSpout,KafkaSpout等。

Bolts:Bolts是逻辑处理单元。Spouts将数据传递到Bolts和Bolts过程,并产生新的输出流。Bolts可以执行过滤,聚合,加入,与数据源和数据库交互的操作。Bolts接收数据并发射到一个或多个Bolts。 “IBolt”是实现Bolts的核心接口。一些常见的接口是IRichBolt,IBasicBolt等。

storm的核心组件

在这里插入图片描述
Nimbus(主节点):Nimbus是Storm集群的主节点。集群中的所有其他节点称为工作节点。主节点负责在所有工作节点之间分发数据,向工作节点分配任务和监视故障。

Supervisor(工作节点):遵循指令的节点被称为Supervisors。Supervisor有多个工作进程,它管理工作进程以完成由nimbus分配的任务。

Worker process(工作进程) 工作进程将执行与特定拓扑相关的任务。工作进程不会自己运行任务,而是创建执行器并要求他们执行特定的任务。工作进程将有多个执行器。

Executor(执行者):执行器只是工作进程产生的单个线程。执行器运行一个或多个任务,但仅用于特定的spout或bolt。

Task(任务):任务执行实际的数据处理。所以,它是一个spout或bolt。

ZooKeeper框架:Apache的ZooKeeper的是使用群集(节点组)自己和维护具有强大的同步技术共享数据之间进行协调的服务。Nimbus是无状态的,所以它依赖于ZooKeeper来监视工作节点的状态。

ZooKeeper的帮助supervisor与nimbus交互。它负责维持nimbus,supervisor的状态。

Nimbus 主控节点,Supervisor 一台台主机节点,Supervisor 里有多个 worker (进程),worker 里有多个 executor(线程),executor里有多个任务。
总结:Nimbus下命令(分配任务),zk监督执行(worker、Supervisor 心跳监控),Supervisor下载代码,创建worker 和线程等

api简介

1. component组件

基本接口
IComponent 接口
ISpout 接口
IRichSpout 接口
IStateSpout 接口
IRichStateSpout 接口
IBolt 接口
IRichBolt 接口
IBasicBolt 接口
基本抽象类
BaseComponent 抽象类
baseRichSpout 抽象类
BaseRichBolt 抽象类
BaseTransactionalBolt 抽象类
BaseBasicBolt 抽象类

2. spout

spout的最顶层抽象是ISpout接口
在这里插入图片描述

  1. open()初始化
  2. close()在该spout关闭前执行,但是并不能得到保证其一定被执行,kill -9 时不执行,storm kill{topoName}时执行
  3. active()当spout已经从失效模式中激活时被调用。该spout的nextTuple()方法很快就被调用
  4. deaactive()当spout已经失效时被调用。
  5. nextTuple()发射元组到输出收集器
  6. ack()成功处理tuple回调方法
    (7) fail()处理失败tuple回调方法
    原则:通常情况下(Shell 和事务型的除外),实现一个Spout,可以直接实现接口IRichSpout,如果不想写多余的代码,可以直接继承BaseRichSpout。。

3. bolt

bolt的最顶层抽象是ISpout接口
在这里插入图片描述

  1. prepare()初始化时,提供了Bolt执行所需要的环境
  2. execute()接受一个tuple进行业务处理,也可emit数据到下-级组件。
  3. cleanup()清场关闭

4. spout的tail特性

storm可以实时监测文件数据,当文件数据变化时,storm自动读取

分组策略

stream grouping用来定义一个stream应该如何分配给Bolts. 上面的多个Executors (多线程、
多并发)。
Storm里面有7种类型的stream grouping.

  1. Shuffle Grouping:随机分组,轮询,平均分配。随机派发stream里面的tuple, 保证每个bolt接收到的tuple数目大致相同。
  2. Fields Grouping:按字段分组,比如按userid来分组,具有同样userid的tuple会被分到相同的Bolts 里的一个task,而不同的userid则会被分配到不同的bolts里的task。
  3. All Grouping:广播发送,对于每-一个tuple,所有的bolts都会收到。
  4. Global Grouping: 全局分组,这个tuple被分配到storm中的一个bolt的其中一个task.
    再具体一点就是分配给id值最低的那个task。
  5. Non Grouping:不分组,这stream grouping个分组的意思是说stream 不关心到底谁会收到它的tuple.目前这种分组和Shuffle grouping是-样的效果。在多线程情况下不平均分配。
  6. Direct Grouping: 直接分组,这是-种比较特别的分组方法,用这种分组意味着消息的发送者指定由消息接收者的哪个task处理这个消息。只有被声明为Direct Stream的消息流可以声明这种分组方法。而且这种消息tuple必须使用emitDirect 方法来发射。消息处理者可以通过TopologyContext来获取处理它的消息的task的id (OutputCollector.emit 方法也会返回task的id)。
  7. Local or shuffle grouping:如果目标bolt有一个或者多个task在同一一个工作进程中,tuple将会被随机发送给这些tasks。否则,和普通的Shuffle Grouping行为一致。

并发度

并发度:用户指定一个任务,可以被多个线程执行, 并发度的数量等于线程executor的数量。

Task就是具体的处理逻辑对象,一个executor线程可以执行-一个或多个tasks,但一般默认每个executor只执行一个task,所以我们往往认为task就是执行线程,其实不是。

Task代表最大并发度,一个component的task 数是不会改变的,但是一个componet的
executer数目是会发生变化的( storm rebalance命令),task 数>=executor数, executor 数代表实际并发数。

在这里插入图片描述

Wordcount例子

设计一个topology,来实现对文件里面的单词出现的频率进行统计
整个topology分为三个部分: .
(1) WordCountSpout:数据源,读取文件一行行数据。
(2) WordCountsplitBolt:负责将单行文本记录切分成单词。
(3) WordCountBolt:负责对单词的频率进行累加工

WordCountSpout:

package wordCount;
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 java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.util.Map;

public class wordCountSpout extends BaseRichSpout {
    private SpoutOutputCollector collector;
    private BufferedReader reader;
    private String str;

    @Override
    public void open(Map map, TopologyContext topologyContext, SpoutOutputCollector spoutOutputCollector) {
        this.collector = collector;
        try {
            this.reader = new BufferedReader(new InputStreamReader(new FileInputStream("e:/wc.log")));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void nextTuple() {
        try{
            //发送数据
            while((str = reader.readLine()) != null){
                collector.emit(new Values(str));
                Thread.sleep(500);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
        outputFieldsDeclarer.declare(new Fields("line"));
    }
}
wordCountSplitBolt:

package wordCount;

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;

public class wordCountSplitBolt extends BaseRichBolt {
    private OutputCollector collector;

    @Override
    public void prepare(Map map, TopologyContext topologyContext, OutputCollector collector) {
        this.collector = collector;
    }

    @Override
    public void execute(Tuple input) {
        //接收数据
        String line = input.getString(0);//Fields("line")
        //截取
        String[] splits = line.split("\t");
        //发出去
        for(String word : splits){
            collector.emit(new Values(word,1));
        }
    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        //声明字段
        declarer.declare(new Fields("word","num"));
    }
}

wordCountBolt:

package wordCount;

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 wordCountBolt extends BaseRichBolt {
    //单词为key;单词出现次数为value
    private Map<String , Integer> map = new HashMap<>();

    @Override
    public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {

    }

    @Override
    public void execute(Tuple input) {
        //获取传递过来的数据
        String word = input.getString(0);
        Integer num = input.getInteger(1);
        //业务处理
        if(map.containsKey(word)){
            Integer count = map.get(word);
            map.put(word,count+num);
        }else {
            map.put(word,num);
        }
        //控制台打印
        System.err.println(Thread.currentThread().getId()+"  word:"+ word+"  num:"+num);
    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {

    }
}

wordCountMain:

package wordCount;

import org.apache.storm.Config;
import org.apache.storm.LocalCluster;
import org.apache.storm.StormSubmitter;
import org.apache.storm.topology.TopologyBuilder;
import org.apache.storm.tuple.Fields;

public class wordCountMain {
    public static void main(String[] args) {
        //创建拓扑对象
        TopologyBuilder builder = new TopologyBuilder();
        builder.setSpout("wordCountSpout",new wordCountSpout(),1);

        builder.setBolt("wordCountSplitBolt",new wordCountSplitBolt(),4).fieldsGrouping("WordCountSpout",new Fields("love"));
        builder.setBolt("wordCountBolt",new wordCountBolt(),1).fieldsGrouping("wordCountSplitBolt",new Fields("word"));
        
        Config config = new Config();
        config.setNumWorkers(2);
        //提交程序
        if(args.length > 0){
            //集群提交
            try {
                StormSubmitter.submitTopology("wordCountTopology" ,config,builder.createTopology());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else {
            //本地提交
            LocalCluster localCluster = new LocalCluster();
            localCluster.submitTopology("wordCountTopology",config,builder.createTopology());
        }
    }
}

PV例子(使用基本接口)

UVSpout:(读数据)

package UV;

import org.apache.storm.spout.SpoutOutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.IRichSpout;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Values;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.util.Map;

public class UVSpout implements IRichSpout {
    private SpoutOutputCollector SpoutOutputCollector;
    private BufferedReader reader;

    @Override
    public void open(Map map, TopologyContext topologyContext, SpoutOutputCollector spoutOutputCollector) {
        this.SpoutOutputCollector =SpoutOutputCollector;
        try {
            reader = new BufferedReader(new InputStreamReader(new FileInputStream("e:/website2.log")));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void close() {

    }

    @Override
    public void activate() {

    }

    @Override
    public void deactivate() {

    }

    private String str = null;
    @Override
    public void nextTuple() {
        try{
            //发送数据
            while((str = reader.readLine()) != null){
                SpoutOutputCollector.emit(new Values(str));
                Thread.sleep(500);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void ack(Object o) {

    }

    @Override
    public void fail(Object o) {

    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
        outputFieldsDeclarer.declare(new Fields("log"));
    }

    @Override
    public Map<String, Object> getComponentConfiguration() {
        return null;
    }
}

UVSplitBolt:(截取ip,计数为1package UV;

import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.IRichBolt;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Tuple;
import org.apache.storm.tuple.Values;

import java.util.Map;

public class UVSplitBolt  implements IRichBolt {
    private OutputCollector OutputCollector;
    @Override
    public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {
        this.OutputCollector = OutputCollector;
    }

    @Override
    public void execute(Tuple input) {
        //获取数据
        String line = input.getString(0);
        //截取
        String[] splits = line.split("\t");
        String ip = splits[3];
        //发出去
        OutputCollector.emit(new Values(ip,1));
    }

    @Override
    public void cleanup() {

    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
        outputFieldsDeclarer.declare(new Fields("ip","num"));
    }

    @Override
    public Map<String, Object> getComponentConfiguration() {
        return null;
    }
}

UVSumBolt:(存入map,累加求总数)

package UV;

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

import java.util.HashMap;
import java.util.Map;

public class UVSumBolt implements IRichBolt {
    private Map<String,Integer> map = new HashMap<>();

    @Override
    public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {

    }

    @Override
    public void execute(Tuple input) {
        String ip = input.getString(0);
        Integer num = input.getInteger(1);
        if (map.containsKey(ip)){
            Integer count = map.get(ip);
            map.put(ip,count+num);
        }else {
            map.put(ip,num);
        }
        System.out.println(ip+" "+num);
    }

    @Override
    public void cleanup() {

    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {

    }

    @Override
    public Map<String, Object> getComponentConfiguration() {
        return null;
    }
}

UVMain :

package UV;
import org.apache.storm.Config;
import org.apache.storm.LocalCluster;
import org.apache.storm.topology.TopologyBuilder;


public class UVMain {
    public static void main(String[] args) {
        TopologyBuilder builder = new TopologyBuilder();
        builder.setSpout("UVSpout",new UVSpout(),1);
        builder.setBolt("UVSplitBolt",new UVSplitBolt(),4).shuffleGrouping("UVSpout");
        builder.setBolt("UVSumBolt",new UVSumBolt(),1).shuffleGrouping("UVSplitBolt");
        Config config = new Config();
        config.setNumWorkers(2);
        LocalCluster localCluster = new LocalCluster();
        localCluster.submitTopology("uvtopology",config,builder.createTopology());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值