Flink越过Kafka中的不良消息:“毒药消息”

时间:2018-06-20 08:51:26

标签: apache-kafka apache-flink flink-streaming

我第一次尝试使它起作用,所以请耐心等待。我试着 使用Kafka学习检查点并处理“不良”消息,然后重新启动 不会失去状态。

用例: 使用检查点。 从卡夫卡读取整数流,保持连续的总和。 如果读取了“不良” Kafka消息,请重新启动应用,跳过“不良”消息,继续 州。我的信息流看起来像这样:

set1,5
set1,7
set1,foobar
set1,6

我希望我的应用保持其所见整数的连续总和,然后重新启动 如果它崩溃而没有丢失状态,则应用程序行为/运行总和为:
5,
12,
应用程序崩溃并重新启动,读取检查点
18
等等

但是,我发现我的应用重新启动时,它一直在读取错误的“ foobar” 消息,并没有过去。源代码如下。当我的时候,映射器炸弹 尝试将“ foobar”解析为整数。 如何修改应用程序以获取过去的“中毒”消息?

    env.enableCheckpointing(1000L);   


   env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE); 
        env.getCheckpointConfig().setMaxConcurrentCheckpoints(1); 
        env.getCheckpointConfig().setMinPauseBetweenCheckpoints(500L); 
        env.getCheckpointConfig().setCheckpointTimeout(10000); 
        env.getCheckpointConfig().setMaxConcurrentCheckpoints(1); 
        env.setStateBackend(new 
        FsStateBackend("hdfs://mymachine:9000/flink/checkpoints")); 

        Properties properties = new Properties(); 
        properties.setProperty("bootstrap.servers", BROKERS); 
        properties.setProperty("zookeeper.connect", ZOOKEEPER_HOST); 
        properties.setProperty("group.id", "consumerGroup1"); 

        FlinkKafkaConsumer08 kafkaConsumer = new FlinkKafkaConsumer08<>(topicName, 
        new SimpleStringSchema(), properties); 
        DataStream<String> messageStream = env.addSource(kafkaConsumer); 

        DataStream<Tuple2&lt;String,Integer>> sums = messageStream 
          .map(new NumberMapper()) 
          .keyBy(0) 
          .sum(1);  
          sums.print(); 


                private static class NumberMapper implements 
        MapFunction<String,Tuple2<String,Integer>> { 
                        public Tuple2<String,Integer> map(String input) throws Exception { 
                                return parseData(input); 
                        } 

                        private Tuple2<String,Integer> parseData(String record) { 

                                String[] tokens = record.toLowerCase().split(","); 

                                // Get Key 
                                String key = tokens[0]; 

                                // Get Integer Value 
                                String integerValue = tokens[1]; 
                                System.out.println("Trying to Parse=" + integerValue); 
                                Integer value = Integer.parseInt(integerValue); 

                                // Build Tuple
                                return new Tuple2<String,Integer>(key, value); 
                        } 

                } 

1 个答案:

答案 0 :(得分:1)

您可以将NumberMapper更改为FlatMap并过滤掉无效元素:

private static class NumberMapper implements FlatMapFunction<String, Tuple2<String, Integer>> { 
        public void flatMap(String input, Collector<Tuple2<String, Integer>> collector) throws Exception { 
                Optional<Tuple2<String, Integer>> optionalResult = parseData(input); 

                optionalResult.ifPresent(collector::collect);
        } 

        private Optional<Tuple2<String, Integer>> parseData(String record) { 

                String[] tokens = record.toLowerCase().split(","); 

                // Get Key 
                String key = tokens[0]; 

                // Get Integer Value 
                String integerValue = tokens[1]; 

                try {
                        Integer value = Integer.parseInt(integerValue); 
                        // Build Tuple
                        return Optional.of(Tuple2.of(key, value)); 
                } catch (NumberFormatException e) {
                        return Optional.empty();
                }
        } 
}