繁体   English   中英

Flink DataStream 如何将一个自定义的 POJO 组合成另一个 DataStream

[英]Flink How do DataStream combine a custom POJO into another DataStream

我想将 DataStream 转换为带有架构信息的 DataStream

输入

args[0] 数据流

{"fields":["China","Beijing"]}

args[1] 架构

message spark_schema {
  optional binary country (UTF8);
  optional binary city (UTF8);
}

期待输出

{"country":"china", "city":"beijing"}

我的代码是这样的

public DataStream<String> convert(DataStream source, MessageType messageType) {

        SingleOutputStreamOperator<String> dataWithSchema = source.map((MapFunction<Row, String>) row -> {
            JSONObject data = new JSONObject();
            this.fields = messageType.getFields().stream().map(Type::getName).collect(Collectors.toList());
            for (int i = 0; i < fields.size(); i++) {
                data.put(fields.get(i), row.getField(i));
            }
            return data.toJSONString();
        });
        return dataWithSchema;
    }

异常错误

Exception in thread "main" org.apache.flink.api.common.InvalidProgramException: Object com.xxxx.ParquetDataSourceReader$$Lambda$64/1174881426@d78795 is not serializable
    at org.apache.flink.api.java.ClosureCleaner.ensureSerializable(ClosureCleaner.java:180)
    at org.apache.flink.streaming.api.environment.StreamExecutionEnvironment.clean(StreamExecutionEnvironment.java:1823)
    at org.apache.flink.streaming.api.datastream.DataStream.clean(DataStream.java:188)
    at org.apache.flink.streaming.api.datastream.DataStream.map(DataStream.java:590)

但下面的代码工作正常

public DataStream<String> convert(DataStream source, MessageType messageType) {
        if (this.fields == null) {
            throw new RuntimeException("The schema of AbstractRowStreamReader is null");
        }

        List<String> field = messageType.getFields().stream().map(Type::getName).collect(Collectors.toList());
        SingleOutputStreamOperator<String> dataWithSchema = source.map((MapFunction<Row, String>) row -> {
            JSONObject data = new JSONObject();
            for (int i = 0; i < field.size(); i++) {
                data.put(field.get(i), row.getField(i));
            }
            return data.toJSONString();
        });
        return dataWithSchema;
    }

Flink map operator 如何结合外部复杂的 POJO?

为了让 Flink 跨任务分发代码,代码需要完全Serializable 在你的第一个例子中,它不是; 在第二个是。 特别是, Type::getName将生成一个不是Serializable的 lambda。

要获得可Serializable的 lambda,您需要将其显式转换为可序列化接口(例如 Flink MapFunction )或将其与(Serializable & Function)

由于第二个也在节省计算,因此无论如何都会更好。 Convert 将在作业编译期间只执行一次,而DataStream#map会为每条记录调用。 如果这不清楚,我建议在 IDE 中执行它并使用断点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM