1、Spout消息的生产者(即是Tuple的创建者)
public interface IRichSpout extends ISpout, IComponent{}
// BaseRichSpout 重写了IRichSpout接口的所有方法,都是空函数体
public abstract class BaseRichSpout extends BaseComponent implements IRichSpout {}
1.1 Spout相关核心接口
1.1.1 ISpout接口
import org.apache.storm.task.TopologyContext;
import java.util.Map;
import java.io.Serializable;
public interface ISpout extends Serializable {
void open(Map conf, TopologyContext context, SpoutOutputCollector collector);
void close();
void activate();
void deactivate();
void nextTuple();
void ack(Object msgId);
void fail(Object msgId);
}
1.1.2 IComponent接口
package org.apache.storm.topology;
import java.io.Serializable;
import java.util.Map;
public interface IComponent extends Serializable {
void declareOutputFields(OutputFieldsDeclarer declarer);
Map<String, Object> getComponentConfiguration();
}
1.1.3 ISpoutOutputCollector:输出收集器
public interface ISpoutOutputCollector extends IErrorReporter{
//返回收到这些元组的task id
List<Integer> emit(String streamId, List<Object> tuple, Object messageId);
void emitDirect(int taskId, String streamId, List<Object> tuple, Object messageId);
long getPendingCount();
}
1.2 Spout自定义实现
1.2.1 open函数实现
public void open(Map conf, TopologyContext context, SpoutOutputCollector collector)
1、在任务集群的工作进程内被初始化,提供spout执行所需要的环境
2、conf参数是这个spout的strom配置,提供给拓扑与这台主机上的集群配置一起合并
3、context主要用来获取这个任务在拓扑中的位置信息,包括该任务的id,该任务的组件id,输入和输出消息等
4、collector是收集器,用于从spout发送元祖,收集器是线程安全的,应该作为这个spout对象的实例变量进行保存。
1.2.2 close函数实现
public void close()
当ISpout关闭时被调用,不能保证close一定被调用,因为在集群中可以使用kill -9 直接杀死工作进程/本地模式除外。
1.2.3 activate与deactivate函数实现
public void activate()
当spout从失效模式中激活的时候被调用
public void deactivate()
当spout已经失效的时候被调用,在失效期间,nextTuple()方法不会被调用
1.2.4 nextTuple函数
1、非阻塞,如果没有元组可以发送,可休眠,不浪费CPU
2、发送元祖到输出收集器SpoutOutputCollector
1.2.5 ack和fail函数
public void ack(Object msgId)
1、storm断定该spout发送的标识符msgId的元祖已经被成功处理时调用
2、ack()方法调用后将消息移除队列(之前的消息是挂起的)
public void fail(Object msgId)
1、storm断定该spout发送的标识符msgId的元祖没有被成功处理时调用
2、fail()方法调用后将消息放入队列(之前的消息是挂起的)
1.2.6 declareOutputFields函数
public void declareOutputFields(OutputFieldsDeclarer declarer){declarer.declare(new Fields("sentence"));}
1、负责声明输出字段,与(collector.emit(new Values(curMsg),msgId);)中new Value一一对应。
2、public Fields(String... fields) {this(Arrays.asList(fields));}
3、public Values(Object... vals)//Values类继承自ArrayList<Object>
1.3 Spout与第三方工具结合
1.3.1 spout与kafka consumer整合
pom文件依赖
<dependency>
<groupId>org.apache.storm</groupId>
<artifactId>storm-kafka-client</artifactId>
<version>1.1.1</version>
</dependency>
自定义kafka-spout的配置类,需要定义翻译函数(ConsumerRecord->storm 的tuple),以及kafka的消费者相关参数。
public class BusSpoutConfig {
/**
* kafka消息翻译函数,record-->BusGPS对象
*/
private static Func<ConsumerRecord<String, String>, List<Object>> record2BusGPS = new Func<ConsumerRecord<String, String>, List<Object>>() {
ObjectMapper objectMapper = new ObjectMapper();
@Override
public List<Object> apply(ConsumerRecord<String, String> record) {
String message = record.value();
BusGPS busGPS = null;
try {
busGPS = objectMapper.readValue(message, BusGPS.class);
} catch (IOException e) {
e.printStackTrace();
log.error("busGPS转换错误:{}", e.getMessage());
}
return new Values(busGPS);
}
};
public static KafkaSpoutConfig<String, String> newKafkaSpoutConfig() {
return KafkaSpoutConfig
.builder(PropUtils.getProperty("kafka.servers"), PropUtils.getProperty("bus.gps.topic"))//设置bootstrapServers和topic
.setProp(ConsumerConfig.GROUP_ID_CONFIG, "busSpoutGroup")//设置消费组
.setProp(ConsumerConfig.MAX_POLL_INTERVAL_MS_CONFIG, 600000)//消费者最大心跳时间间隔
// .setProp(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, 200)
.setRecordTranslator(record2BusGPS, new Fields("busGPS"))//设置消息翻译函数
.setOffsetCommitPeriodMs(10000)//设置提交offset周期
.setFirstPollOffsetStrategy(LATEST)//设置第一次拉取消息时offset位置
// .setMaxUncommittedOffsets(500)//Defines the max number of polled offsets (records) that can be pending commit, before another poll can take place
.build();
}
}
kafkaSpout实例化时,传入config类实例,指定并行度。
/* 构建topo*/
private StormTopology buildTopology() {
TopologyBuilder builder = new TopologyBuilder();
//设置spout
builder.setSpout("KafkaSpout", new KafkaSpout<>(BusSpoutConfig.newKafkaSpoutConfig()), 3);
//设置bolt
builder.setBolt("mapRealtimeBolt", new BusMapRealtimeBolt().withTumblingWindow(new BaseWindowedBolt.Duration(1, TimeUnit.MINUTES)), 1).localOrShuffleGrouping("KafkaSpout");
return builder.createTopology();
}
来源:CSDN
作者:luguanghui2007
链接:https://blog.csdn.net/luguanghui2007/article/details/104576488