Apache flink 在Flink中解析JSON时如何处理异常

Apache flink 在Flink中解析JSON时如何处理异常,apache-flink,flink-streaming,Apache Flink,Flink Streaming,我正在使用flink 1.4.2从Kafka读取数据,并使用JSONDeserializationSchema将其解析到ObjectNode。如果传入记录不是有效的JSON,则我的Flink作业将失败。我想跳过这个坏记录,而不是不及格 FlinkKafkaConsumer010<ObjectNode> kafkaConsumer = new FlinkKafkaConsumer010<>(TOPIC, new JSONDeserializa

我正在使用flink 1.4.2从Kafka读取数据,并使用JSONDeserializationSchema将其解析到ObjectNode。如果传入记录不是有效的JSON,则我的Flink作业将失败。我想跳过这个坏记录,而不是不及格

FlinkKafkaConsumer010<ObjectNode> kafkaConsumer =
                new FlinkKafkaConsumer010<>(TOPIC, new JSONDeserializationSchema(), consumerProperties);
DataStream<ObjectNode> messageStream = env.addSource(kafkaConsumer);
messageStream.print();

最简单的解决方案是实现您自己的反序列化模式并包装JSONDeserializationSchema。然后,您可以捕获异常并忽略它或执行自定义操作。

最简单的解决方案是实现您自己的反序列化模式并包装JSONDeserializationSchema。然后,您可以捕获异常并忽略它或执行自定义操作。

正如@twalthr所建议的,我通过复制JSONDeserializationSchema和添加异常处理实现了自己的反序列化架构

import org.apache.flink.api.common.serialization.AbstractDeserializationSchema;
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;

public class CustomJSONDeserializationSchema extends AbstractDeserializationSchema<ObjectNode> {

    private ObjectMapper mapper;

    @Override
    public ObjectNode deserialize(byte[] message) throws IOException {
        if (mapper == null) {
            mapper = new ObjectMapper();
        }

        ObjectNode objectNode;
        try {
            objectNode = mapper.readValue(message, ObjectNode.class);
        } catch (Exception e) {
            ObjectMapper errorMapper = new ObjectMapper();
            ObjectNode errorObjectNode = errorMapper.createObjectNode();
            errorObjectNode.put("jsonParseError", new String(message));
            objectNode = errorObjectNode;
        }
        return objectNode;
    }

    @Override
    public boolean isEndOfStream(ObjectNode nextElement) {
        return false;
    }

}

正如@twalthr所建议的,我通过复制JSONDeserializationSchema并添加异常处理来实现自己的反序列化模式

import org.apache.flink.api.common.serialization.AbstractDeserializationSchema;
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;

public class CustomJSONDeserializationSchema extends AbstractDeserializationSchema<ObjectNode> {

    private ObjectMapper mapper;

    @Override
    public ObjectNode deserialize(byte[] message) throws IOException {
        if (mapper == null) {
            mapper = new ObjectMapper();
        }

        ObjectNode objectNode;
        try {
            objectNode = mapper.readValue(message, ObjectNode.class);
        } catch (Exception e) {
            ObjectMapper errorMapper = new ObjectMapper();
            ObjectNode errorObjectNode = errorMapper.createObjectNode();
            errorObjectNode.put("jsonParseError", new String(message));
            objectNode = errorObjectNode;
        }
        return objectNode;
    }

    @Override
    public boolean isEndOfStream(ObjectNode nextElement) {
        return false;
    }

}

Flink改进了FlinkKafkaConsumer的空记录处理

当反序列化模式遇到损坏的消息时,有两种可能的设计选择。它可以抛出导致管道重新启动的IOException,也可以返回null,其中Flink Kafka使用者将静默跳过损坏的消息


有关更多详细信息,您可以看到这一点。

Flink改进了FlinkKafkaConsumer的空记录处理

当反序列化模式遇到损坏的消息时,有两种可能的设计选择。它可以抛出导致管道重新启动的IOException,也可以返回null,其中Flink Kafka使用者将静默跳过损坏的消息

有关更多详细信息,请参见此

messageStream
        .filter((event) -> {
            if(event.has("jsonParseError")) {
                LOG.warn("JsonParseException was handled: " + event.get("jsonParseError").asText());
                return false;
            }
            return true;
        }).print();