Storm ack容错机制案例

Ack机制:

spout 发出一条数据后需要知道数据处理成功和失败的状态,如失败的消息重新发送。
1. 自定义spoout实现BeseRichSpout,重写ack、fai方法。
2. 在自定义的spout 发送数据的时候,需要制定messageid,messageid 是一个Object.
3. 当消息处理成功或者失败之后,Storm框架会将messageid传回来。如果消息要重发,直接通过messageid找到或直接转化成数据内容进行重发。
4. 自定义Bolt实现BaseRichBolt
5. 在bolt的execute中进行两个操作: 发送数据时,需要制定血缘关系,锚点collector.emit(父tupe,new 子Tupe);当execute处理完成业务逻辑的时候,需要告诉storm框架当前阶段的处理状态collector.ack(tupe)
如果在编写storm程序时,在bolt环节忘记了手动ack或fail,怎么办?
忘了手动ack或fail,storm框架会等待反馈,达超时阈值之后,就直接给fail。
如果在编写storm程序时,bolt环节忘了标示锚点,怎么办?
忘了标示锚点,及时完了标血缘关系。storm会认为你不关系后面阶段的处理。
Storm BaseRichClient Api 可能有点繁琐,可以使用BaseBasicBolt
如果实现了BaseBasicBolt,就不需要锚点,不需要手动ack或fail

基于BaseRichSpout、BaseRichBolt

这里写图片描述

AckSpout:

public class AckSpout extends BaseRichSpout {
    private SpoutOutputCollector collector;

    //初始化方法
    public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
        this.collector = collector;
    }

    //上帝之手,循环调用,每调用过一次就发送一条消息
    public void nextTuple() {
        //生产一条数据
        String uuid = UUID.randomUUID().toString().replace("_", "");
        collector.emit(new Values(uuid),new Values(uuid));
        try {
            Thread.sleep(10*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //定义发送的字段
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("uuid"));
    }

    @Override
    public void ack(Object msgId) {
        System.out.println("消息处理成功" + msgId);
    }

    @Override
    public void fail(Object msgId) {
        System.out.println("消息处理失败" + msgId);
        collector.emit((List)msgId,msgId );
    }
}

Bolt1

public class Bolt1 extends BaseRichBolt {
    private OutputCollector collector;

    //初始化方法 只调用一次
    public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
        this.collector = collector;
    }

    //被循环调用
    public void execute(Tuple input) {
        collector.emit(input,new Values(input.getString(0)));
        System.out.println("bolt1的execute方法被调用一次" + input.getString(0));
        collector.ack(input);
    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("uuid"));
    }
}

Bolt2

public class Bolt2 extends BaseRichBolt {
    private OutputCollector collector;

    //初始化方法 只调用一次
    public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
        this.collector = collector;
    }

    //被循环调用
    public void execute(Tuple input) {
        collector.emit(input,new Values(input.getString(0)));
        System.out.println("bolt2的execute方法被调用一次" + input.getString(0));
        collector.ack(input);
    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("uuid"));
    }
}

Bolt3

public class Bolt3 extends BaseRichBolt {
    private OutputCollector collector;

    //初始化方法 只调用一次
    public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
        this.collector = collector;
    }

    //被循环调用
    public void execute(Tuple input) {
        collector.emit(input,new Values(input.getString(0)));
        System.out.println("bolt3的execute方法被调用一次" + input.getString(0));
        collector.fail(input);
    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("uuid"));
    }
}

Bolt4

public class Bolt4 extends BaseRichBolt {
    private OutputCollector collector;

    //初始化方法 只调用一次
    public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
        this.collector = collector;
    }

    //被循环调用
    public void execute(Tuple input) {
        collector.emit(input,new Values(input.getString(0)));
        System.out.println("bolt4的execute方法被调用一次" + input.getString(0));
        collector.ack(input);
    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("uuid"));
    }
}

AckTopologyDriver

public class AckTopologyDriver {
    public static void main(String[] args) throws AlreadyAliveException, InvalidTopologyException {
        //1、准备任务信息
        TopologyBuilder topologyBuilder = new TopologyBuilder();
        topologyBuilder.setSpout("mySpout", new AckSpout(), 1);
        topologyBuilder.setBolt("bolt1", new Bolt1(),1).shuffleGrouping("mySpout");
        topologyBuilder.setBolt("bolt2", new Bolt2(),1).shuffleGrouping("bolt1");
        topologyBuilder.setBolt("bolt3", new Bolt3(),1).shuffleGrouping("bolt2");
        topologyBuilder.setBolt("bolt4", new Bolt4(),1).shuffleGrouping("bolt3");

        Config config = new Config();
        config.setNumWorkers(2);
        StormTopology stormTopology = topologyBuilder.createTopology();
        LocalCluster localCluster = new LocalCluster();
        localCluster.submitTopology("wordcount", config, stormTopology);

    }
}

基于BaseRichSpout、BaseBasicBolt

这里写图片描述
AckSpout

public class AckSpout extends BaseRichSpout {
    private SpoutOutputCollector collector;

    //初始化方法
    public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
        this.collector = collector;
    }

    //上帝之手,循环调用,每调用过一次就发送一条消息
    public void nextTuple() {
        //生产一条数据
        String uuid = UUID.randomUUID().toString().replace("_", "");
        collector.emit(new Values(uuid),new Values(uuid));
        try {
            Thread.sleep(10*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //定义发送的字段
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("uuid"));
    }

    @Override
    public void ack(Object msgId) {
        System.out.println("消息处理成功" + msgId);
    }

    @Override
    public void fail(Object msgId) {
        System.out.println("消息处理失败:重发" + msgId);
        collector.emit((List)msgId,msgId );
    }
}

Bolt1

public class Bolt1 extends BaseBasicBolt {
    @Override
    public void execute(Tuple input, BasicOutputCollector collector) {
        collector.emit(new Values(input.getString(0)));
    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("uuid"));
    }
}

Bolt2

public class Bolt2 extends BaseBasicBolt {
    @Override
    public void execute(Tuple input, BasicOutputCollector collector) {
        collector.emit(new Values(input.getString(0)));
    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("uuid"));
    }

Bolt3

public class Bolt3 extends BaseBasicBolt {
    @Override
    public void execute(Tuple input, BasicOutputCollector collector) {
//        collector.emit(new Values(input.getString(0)));
        throw new FailedException();
    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("uuid"));
    }
}

Bolt4

public class Bolt4 extends BaseBasicBolt {
    @Override
    public void execute(Tuple input, BasicOutputCollector collector) {
        collector.emit(new Values(input.getString(0)));
    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("uuid"));
    }
}

AckTopologyDriver

public class AckTopologyDriver {
    public static void main(String[] args) throws AlreadyAliveException, InvalidTopologyException {
        //1、准备任务信息
        TopologyBuilder topologyBuilder = new TopologyBuilder();
        topologyBuilder.setSpout("mySpout", new AckSpout(), 1);
        topologyBuilder.setBolt("bolt1", new Bolt1(), 1).shuffleGrouping("mySpout");
        topologyBuilder.setBolt("bolt2", new Bolt2(), 1).shuffleGrouping("bolt1");
        topologyBuilder.setBolt("bolt3", new Bolt3(), 1).shuffleGrouping("bolt2");
        topologyBuilder.setBolt("bolt4", new Bolt4(), 1).shuffleGrouping("bolt3");

        Config config = new Config();
        config.setNumWorkers(2);
        StormTopology stormTopology = topologyBuilder.createTopology();
        LocalCluster localCluster = new LocalCluster();
        localCluster.submitTopology("wordcount", config, stormTopology);

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值