第1关:Storm 通信机制


任务描述

本关任务:完成 Storm 通信机制的验证代码。

相关知识

为了完成本关任务,你需要掌握: 1.简介; 2.Storm 通信机制的具体细节; 3.Worker 进程间通信分析; 4.Storm 提交任务流程。

简介

Worker 间的通信经常需要通过网络跨节点进行,Storm 使用 ZeroMQ 或 Netty(0.9 以后默认使用)作为进程间通信的消息框架。

Worker 进程内部通信:不同 worker 的 thread 通信使用 LMAX Disruptor 来完成。

不同 topologey 之间的通信,Storm 不负责,需要自己想办法实现,例如使用 kafka 等;

Worker 进程间消息传递机制,消息的接收和处理的大概流程见下图:

,

Storm 通信机制的具体细节

对于 worker 进程来说,为了管理流入和传出的消息,每个 worker 进程有一个独立的接收线程(对配置的 TCP 端口 supervisor.slots.ports 进行监听);

每个 executor 有自己的 sendQueuereceiveQueue

Worker 接收线程将收到的消息通过 task 编号传递给对应的 executor (一个或多个)的 receiveQueue。

每个 executor 有单独的线程分别来处理 spout/bolt 的业务逻辑,业务逻辑输出的中间数据会存放在 sendQueue 中,当 executor 的 sendQueue 中的 tuple 达到一定的阀值,executor 的发送线程将批量获取 sendQueue 中的 tuple,并发送到 TransferQueue 中。

每个 worker 进程控制一个或多个 executor 线程,用户可在代码中进行配置。其实就是我们在代码中设置的并发度个数。

一个 worker 进程运行一个专用的接收线程来负责将外部发送过来的消息移动到对应的 executor 线程的 receiveQueue 中。

TransferQueue 的大小由参数 topology.transfer.buffer.size 来设置。TransferQueue 的每个元素实际上代表一个 tuple 的集合。

TransferQueue 的大小由参数 topology.transfer.buffer.size 来设置。

executor的sendQueue 的大小用户可以自定义配置。

executor的receiveQueue 的大小用户可以自定义配置。

Worker 进程间通信分析

,

1、 Worker 接受线程通过网络接受数据,并根据 Tuple 中包含的 taskId,匹配到对应的 executor;然后根据 executor 找到对应的 incoming-queue,将数据存发送到 receiveQueue 队列中。 2、 业务逻辑执行现成消费 receiveQueue 的数据,通过调用 Bolt 的 execute(xxxx) 方法,将 Tuple 作为参数传输给用户自定义的方法 3、 业务逻辑执行完毕之后,将计算的中间数据发送给 sendQueue 队列,当 sendQueue 中的 tuple 达到一定的阀值,executor 的发送线程将批量获取 sendQueue 中的 tuple,并发送到 Worker 的 TransferQueue 中 4、 Worker 发送线程消费 TransferQueue 中数据,计算 Tuple 的目的地,连接不同的 node+port 将数据通过网络传输的方式传送给另一个的 Worker。 5、 另一个 worker 执行以上步骤 1 的操作。

Storm 提交任务流程

,

1、client : 客户端运行 nimbus 时,会调用 strom 的 python 脚本,该脚本为每个命令编写一个方法。

2、nimbus: nimbus 启动后,接受客户端提交的任务,createTopology() 会将程序员编写的 spout 对象和 bolt 对象序列化,并将用户 jar 包上传到 nimbus 物理节点目录下,进行改名。

nimbus 接受到任务后,会将任务分配(task 总数/ worker 总数),分配会产生一个 assignment 对象,该对象会保存到 zookeeper 中。

3、supervisor: supervisor 通过 watch 机制,从 zookeeper 上拉取任务信息,分辨出属于自己的任务。

supervisor 根据自己的任务信息,启动自己的 worker, 并分配一个端口。

4、worker: woker 启动后,连接 zookeeper,拉取任务。worker 通过反序列化,得到程序员自己定义的 spout 和 bolt 对象。

worker 根据任务类型,分别执行 spout 任务和 bolt 任务。

spout 的生命周期: opennextTupleoutPutFiled

bolt 的生命周期: prepareexecute(tuple),outPutField

编程要求

根据提示,在右侧编辑器补充代码,通过编写 Topology 来完成 Storm 通信机制的验证。

提示: 如果想要查看更详细的通信机制的产生,可以开启代码的 debug 然后测评后再查看目录 /root/st.log 文件日志。

测试说明

平台会对你编写的代码进行测试:

预期输出:

 
  1. Get Topology instruction, start generating data
  2. Communications received from the spout:source: numberSpout:3, stream: default, id: {}, [5]
  3. The data fetched from the spout is: 5--5
  4. As of this time, the total data obtained is: 15
  5. Get Topology instruction, start generating data
  6. Communications received from the spout:source: numberSpout:3, stream: default, id: {}, [6]
  7. The data fetched from the spout is: 6--6
  8. As of this time, the total data obtained is: 21
  9. Get Topology instruction, start generating data
  10. Communications received from the spout:source: numberSpout:3, stream: default, id: {}, [7]
  11. The data fetched from the spout is: 7--7
  12. As of this time, the total data obtained is: 28

 

 代码如下:

package com.step1;

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

public class NumberTopology {
    public static void main(String[] args) {
        // 创建Topology的构建器
        TopologyBuilder topologyBuilder = new TopologyBuilder();
        
        // 开始构建流程

        //##########BEGIN##########
        topologyBuilder.setSpout("numberspout", new NumberSpout());
        // 设置Spout组件 "numberSpout",使用 NumberSpout 类
        
        topologyBuilder.setBolt("numberBolt", new NumberBolt()).shuffleGrouping("numberspout");
        // 设置Bolt组件 "numberCountBolt",使用 NumberBolt 类,并将其与 "numberSpout" 组件进行 shuffle 分组
        
        // 创建配置对象
        Config conf = new Config();
        // 创建StormTopology实例
        StormTopology topology = topologyBuilder.createTopology();
        // 创建本地集群实例
        LocalCluster localCluster = new LocalCluster();
        // 提交Topology到本地集群执行,Topology名称为 "numberTopology"
        localCluster.submitTopology("numberTopology", conf, topology);
        //##########END##########
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值