大数据之storm

一、离线计算与实时计算

离线计算: 批量获取数据、批量传输数据;周期性计算数据,展示数据;
代表技术: sqoop批量导入,HDFS批量存储,mapreduce批量计算,Hive批量计算数据…
就业方向: hivesql, Hadoop集群运维

实时计算: 数据实时产生,数据实时传输,数据实时计算,实时展示;
代表技术: Flume实时获取数据,kafka/metaq 实时数据存储,storm/Jstrom实时计算数据,redis实时结果缓存,mysql持久化存储…

流式计算一般架构图

在这里插入图片描述
 flume实时采集数据。
 Kafka消息队列,用来临时保存数据。
 Strom实时计算数据。
 Redis实时存储数据。

流式计算就是将源源不断产生的数据实时收集并实时计算,尽可能快的得到计算结果。

二、Strom介绍

Storm用来实时计算数据框架,特点:低延迟、高可用、分布式、可扩展、数据不丢失。提供简单容易理解的接口,便于开发。

Storm与Hadoop区别

 Storm用于实时计算,Storm处理的数据保存在内存中,数据源源不断,通过网络传输进来;

 Hadoop用于离线计算,处理的一批一批数据保存在文件系统中,数据保存在磁盘中。

三、Strom编程模型
在这里插入图片描述

Nimbus : 任务分配,对任务监督;

Zookeeper : 保存任务分配的信息、心跳信息、元数据信息。

Supervisor : 接受任务,并启动worker。worker的数量根据端口号来的;

Worker : 执行任务的具体组件(其实就是一个JVM),可以执行Spout或者bolt两种类型的任务; 一个worker就是一个端口号;

Task : Task=线程=executor, 一个Task属于一个Spout或者Bolt并发任务;

并发度:

用户指定的一个任务,可以被多个线程执行,对应到storm中就是一个task,并发度的数量等于线程的数量。一个任务的多个线程,会被运行在多个Worker(JVM)上,有一种类似于平均算法的负载均衡策略。尽可能减少网络IO;

在这里插入图片描述
一个Strom程序可以获取多个数据源,每个topology的数据都是自己独有的,和其他的topology没有关系。

spout : 获取外部数据源;

Bolt : 业务逻辑处理节点,可以有多个;

Tuple : 消息发送的最小单元,是一个Tuple对象。

四、Strom集群部署

搭建前,需要安装好zookeeper集群

1、准备工作

配置hosts

 vi  /etc/hosts
 
192.168.239.128 storm01 zk01 hadoop01
192.168.239.129 storm02 zk02 hadoop02
192.168.239.130 storm03 zk03 hadoop03

关闭防火墙

chkconfig iptables off  && setenforce 0

创建用户

groupadd realtime && useradd realtime && usermod -a -G realtime realtime

创建工作目录并赋权

mkdir /export
mkdir /export/servers
chmod 755 -R /export

切换到realtime用户下

su realtime

2、解压压缩包

3、修改配置文件

4、分发压缩包

5、启动集群

6、查看集群

访问storm01:8080,即可看到storm的ui界面。

四、Storm操作命令

1、提交任务

storm jar 【jar路径】 【拓扑包名.拓扑类名】 【拓扑名称】

storm jar examples/storm-starter/storm-starter-topologies-0.9.6.jar storm.starter.WordCountTopology wordcount

注意:因为从外部获取数据、结果保存到redis,所以不需要指定输入、输出
路径,这是和hadoop区别

2、杀死任务

storm kill 【拓扑名称】 -w 10

storm kill topology-name -w 10

3、停运任务

storm deactivte 【拓扑名称】

storm deactivte topology-name

五、问题解答

1、worker与topology

一个worker只属于一个topology,一个topology包含多个worker,其实就是这个topology运行在多个worker上。

一个topology要求的worder数量如何不被满足,集群在分配任务时,根据现有的worker先运行的topology。如果当前集群中worder数量为0,那么最新提交的topology将只会标示为active, 不会运行。只有集群有了空闲资源才会被运行。

2、StreamGrouping:(分组策略)

shuffleGrouping(随机分组)、FieldGrouping(按字段分组)、不分组等

3、运行模式

1、集群模式:在集群上运行

2、本地模式:在当前idea上运行,测试代码功能时,可以选择该模式

4、如何指定驱动类中每个组件的并发度数量

1、根据上游的数据量来设置spout并发度

2、根据业务复杂度和execute方法执行时间设置bolt并发度

3、根据集群可用资源配置,一般情况下70%资源利用率

5、如何设置worker的数量

worker的数量根据程序并发度task数量来均分,实际业务场景中,并反复调整

六、worldcount代码编写

1、WordCountTopologMain

package cn.itcast.storm;

import backtype.storm.Config;
import backtype.storm.LocalCluster;
import backtype.storm.StormSubmitter;
import backtype.storm.generated.AlreadyAliveException;
import backtype.storm.generated.InvalidTopologyException;
import backtype.storm.topology.TopologyBuilder;
import backtype.storm.tuple.Fields;

/**
 * Created by maoxiangyi on 2016/4/27.
 */
public class WordCountTopologMain {
    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"));
        //topologyBuilder.setBolt("mybolt2",new MyCountBolt(),4).shuffleGrouping("mybolt1");
        //  config.setNumWorkers(2);
        
        /**
         * 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());
    }
}

2、MySpout

package cn.itcast.storm;

import backtype.storm.spout.SpoutOutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.IRichSpout;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichSpout;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Values;

import java.util.Map;

/**
 * Created by maoxiangyi on 2016/4/27.
 */
public class MySpout extends BaseRichSpout {
    SpoutOutputCollector collector;

    //初始化方法
    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"));
    }
}

3、MySplitBolt

package cn.itcast.storm;
import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.IBasicBolt;
import backtype.storm.topology.IRichBolt;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichBolt;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;

import java.util.Map;

/**
 * Created by maoxiangyi on 2016/4/27.
 */
public class MySplitBolt extends BaseRichBolt {
    OutputCollector collector;
    //初始化方法
    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"));
    }
}

4、MyCountBolt

package cn.itcast.storm;

import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.IBasicBolt;
import backtype.storm.topology.IRichBolt;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichBolt;
import backtype.storm.tuple.Tuple;

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

/**
 * Created by maoxiangyi on 2016/4/27.
 */
public class MyCountBolt extends BaseRichBolt {
    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) {
       //不輸出
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大数据同盟会

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值