1. 可靠的与不可靠的消息
如:
public class WordSpout extends BaseRichSpout{
SpoutOutputCollector _collector;
private static final Integer MAX_FAILS = 2;// 最大失败次数
Map<Integer, String> _messages;// 全部的消息Map
Map<Integer, Integer> _ failureCount;// 消息的失败次数计数Map
Map<Integer, String> _toSend;// 发送消息的MAP
@Override
public void nextTuple() {
if (!_toSend.isEmpty()){
for (Map.Entry<Integer, String> entry : _toSend.entrySet()){
Integer id = entry.getKey();
String message = entry.getValue();
_collector.emit(new Values(message), id);
}
_toSend.clear();
}
Utils.sleep(10);
}
@Override
public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
_collector = collector;
_messages = new HashMap<Integer, String>();
_toSend = new HashMap<Integer, String>();
_transactionFailureCount = new HashMap<Integer, Integer>();
for (int i = 0; i < 10; i++){
_messages.put(i, "message"+String.valueOf(i));
_ failureCount.put(i, 0);
}
_toSend.putAll(_messages);
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word"));
}
@Override
public void ack(Object msgId) {
_messages.remove(msgId);
Integer id = (Integer) msgId;
System.out.println("ack : " + String.valueOf(id));
}
@Override
public void fail(Object msgId) {
Integer id = (Integer) msgId;
System.out.println("fail : " + String.valueOf(id));
Integer failures = _ failureCount.get(id) + 1;
if (failures >= MAX_FAILS){
System.out.println("error, id : [" + id + "] had too many errors [" + _messages.get(id) + "]");
}
else{
_failureCount.put(id, failures);
_toSend.put(id, _messages.get(id));
}
}
}
其实只需要在emit的时候带上id,在bolt的emit中带上tuple参数(后面会说)。这样消息树全成功后就会调用ack方法。有一个失败就会调用fail方法。然后根据业务需要,在这两个方法中添加自己的代码,如失败后重发等等。
如,上面当失败次数大于2时,不是输出一句话,而是抛出一个运行时异常,那么此拓扑会停掉,然后守护者进程会重启一个拓扑。
2. 获取数据
在上面的例子中,都是在初始时写死的几个单词作为数据源进行测试。
生产上spout有三种获取数据的方式:直接连接、消息队列、DRPC
直接连接:
消息队列:
DRPC: