集群可靠性
参考:http://storm.apache.org/releases/1.2.2/Daemon-Fault-Tolerance.html
Worker可靠性
- worker挂掉了,supervisor会重新启动。
- 如果在启动的过程中不断的失败,nimbus没有收到心跳,nimbus会将worker调度到其他supervisor上启动
部署supervisor的机器失去连接
- 如果任务分发的时候失败,nimbus会将任务分发给其他的supervisor
nimbus或者supervisor进程挂掉
- nimbus获取supervisor挂掉后会立刻重启
- nimbus和supervisor挂掉都不回影响worker的继续执行,worker是单独的进程在执行
- nimbus挂掉后不能接收新的topo任务
- 1.0版本后nimbus不在是单节点,是多节点容错
数据可靠性
- best effort(最大努力), at least once(至少执行一次), and exactly once (正好执行一次)
参考:http://storm.apache.org/releases/1.2.2/Guaranteeing-message-processing.html
- 消息处理失败的标准:在特定时间内没有将tuple的消息树处理完成
消息可靠性的处理过程
- spout在发出消息的时候会给每个消息一个msg id
- 如果storm识别到tuple在整个树上处理完了,将会调用spout上的ack方法;如果超时将会调用fail方法
- topology中处理tuple的每一个bolt都会通过OutputCollector来告知storm,当前bolt处理是否成功
参考: https://blog.csdn.net/suifeng3051/article/details/41682441
spout
- 在发送的时候带上messageId,这个id可以是数据库中的主键
- ack() fail()中添加一些处理逻辑。fail后可以选择:1、重试处理;2、记录到日志中
public class NumSpout extends BaseRichSpout{
private SpoutOutputCollector collector;
private Integer number=0;
private List<Integer> idList;
public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
this.collector=collector;
this.idList=context.getComponentTasks("countNum");
}
public void nextTuple() {
collector.emit(new Values(++number),number);
System.out.println("number:"+number);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("num"));
}
@Override
public void ack(Object msgId) {
System.out.println(String.format("msgId is %s. ack!",msgId));
}
@Override
public void fail(Object msgId) {
System.out.println(String.format("msgId is %s. failed!",msgId));
collector.emit(new Values(msgId),msgId);
}
}
bolt处理
- 最终消息处理完后,手动确认消息处理完成
public class SumBolt extends BaseRichBolt {
private int total=0;
private OutputCollector collector;
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
this.collector=collector;
}
public void execute(Tuple input) {
Integer num=input.getIntegerByField("num");
total+=num;
System.out.println("thread:"+Thread.currentThread()+",total:"+total+",receive:"+num);
//确认处理完成
this.collector.ack(input);
}else{
this.collector.fail(input);
}
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
}
}