简体   繁体   English

Flink 默认使用 Kryo 序列化,即使对于 POJO 和 Avro SpecificRecords

[英]Flink defaults to Kryo serialization even for POJOs and Avro SpecificRecords

I am trying to do a POC of Flink State Schema Evolution.我正在尝试做一个 Flink State Schema Evolution 的 POC。 I am using Flink 1.15.0 and Java 11. I tried to create 3 data classes - one for each serialization type:我正在使用 Flink 1.15.0 和 Java 11。我尝试创建 3 个数据类 - 每个序列化类型一个:

  1. io.peleg.kryo.User - Uses java.time.Instant class which I know is not supported for POJO serialization in Flink. io.peleg.kryo.User - 使用java.time.Instant类,我知道 Flink 中的 POJO 序列化不支持该类。
  2. io.peleg.pojo.User - Uses only classic wrapped primitives - Integer , Long , String . io.peleg.pojo.User - 仅使用经典的包装原语 - IntegerLongString The getters, setters and constructors are generated using Lombok. getter、setter 和构造函数是使用 Lombok 生成的。
  3. io.peleg.avro.User - Generated from Avro schema using Avro Maven Plugin. io.peleg.avro.User - 使用 Avro Maven 插件从 Avro 模式生成。

For each class I wrote a stream job that uses a time window to buffer elements and turn them into a list.对于每个类,我编写了一个流作业,它使用时间窗口来缓冲元素并将它们转换为列表。

For each class I tried to do the following:对于每个班级,我都尝试执行以下操作:

  1. Run a job运行作业
  2. Stop with savepoint用保存点停止
  3. Add a field to the data class向数据类添加字段
  4. Submit using savepoint使用保存点提交

For all data classes the submit with savepoint failed with this exception:对于所有数据类,使用保存点提交失败,出现以下异常:

java.lang.Exception: Exception while creating StreamOperatorStateContext.
    at org.apache.flink.streaming.api.operators.StreamTaskStateInitializerImpl.streamOperatorStateContext(StreamTaskStateInitializerImpl.java:255)
    at org.apache.flink.streaming.api.operators.AbstractStreamOperator.initializeState(AbstractStreamOperator.java:268)
    at org.apache.flink.streaming.runtime.tasks.RegularOperatorChain.initializeStateAndOpenOperators(RegularOperatorChain.java:106)
    at org.apache.flink.streaming.runtime.tasks.StreamTask.restoreGates(StreamTask.java:700)
    at org.apache.flink.streaming.runtime.tasks.StreamTaskActionExecutor$1.call(StreamTaskActionExecutor.java:55)
    at org.apache.flink.streaming.runtime.tasks.StreamTask.restoreInternal(StreamTask.java:676)
    at org.apache.flink.streaming.runtime.tasks.StreamTask.restore(StreamTask.java:643)
    at org.apache.flink.runtime.taskmanager.Task.runWithSystemExitMonitoring(Task.java:948)
    at org.apache.flink.runtime.taskmanager.Task.restoreAndInvoke(Task.java:917)
    at org.apache.flink.runtime.taskmanager.Task.doRun(Task.java:741)
    at org.apache.flink.runtime.taskmanager.Task.run(Task.java:563)
    at java.base/java.lang.Thread.run(Unknown Source)
Caused by: org.apache.flink.util.FlinkException: Could not restore keyed state backend for WindowOperator_3983d6bb2f0a45b638461bc99138f22f_(2/2) from any of the 1 provided restore options.
    at org.apache.flink.streaming.api.operators.BackendRestorerProcedure.createAndRestore(BackendRestorerProcedure.java:160)
    at org.apache.flink.streaming.api.operators.StreamTaskStateInitializerImpl.keyedStatedBackend(StreamTaskStateInitializerImpl.java:346)
    at org.apache.flink.streaming.api.operators.StreamTaskStateInitializerImpl.streamOperatorStateContext(StreamTaskStateInitializerImpl.java:164)
    ... 11 more
Caused by: org.apache.flink.runtime.state.BackendBuildingException: Failed when trying to restore heap backend
    at org.apache.flink.runtime.state.heap.HeapKeyedStateBackendBuilder.restoreState(HeapKeyedStateBackendBuilder.java:172)
    at org.apache.flink.runtime.state.heap.HeapKeyedStateBackendBuilder.build(HeapKeyedStateBackendBuilder.java:106)
    at org.apache.flink.runtime.state.hashmap.HashMapStateBackend.createKeyedStateBackend(HashMapStateBackend.java:143)
    at org.apache.flink.runtime.state.hashmap.HashMapStateBackend.createKeyedStateBackend(HashMapStateBackend.java:74)
    at org.apache.flink.runtime.state.StateBackend.createKeyedStateBackend(StateBackend.java:140)
    at org.apache.flink.streaming.api.operators.StreamTaskStateInitializerImpl.lambda$keyedStatedBackend$1(StreamTaskStateInitializerImpl.java:329)
    at org.apache.flink.streaming.api.operators.BackendRestorerProcedure.attemptCreateAndRestore(BackendRestorerProcedure.java:168)
    at org.apache.flink.streaming.api.operators.BackendRestorerProcedure.createAndRestore(BackendRestorerProcedure.java:135)
    ... 13 more
Caused by: com.esotericsoftware.kryo.KryoException: java.lang.IndexOutOfBoundsException: Index 83 out of bounds for length 3
Serialization trace:
favoriteColor (io.peleg.avro.User)
    at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:125)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:528)
    at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:761)
    at com.esotericsoftware.kryo.serializers.CollectionSerializer.read(CollectionSerializer.java:116)
    at com.esotericsoftware.kryo.serializers.CollectionSerializer.read(CollectionSerializer.java:22)
    at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:761)
    at org.apache.flink.api.java.typeutils.runtime.kryo.KryoSerializer.deserialize(KryoSerializer.java:402)
    at org.apache.flink.runtime.state.heap.HeapSavepointRestoreOperation.readKVStateData(HeapSavepointRestoreOperation.java:219)
    at org.apache.flink.runtime.state.heap.HeapSavepointRestoreOperation.readKeyGroupStateData(HeapSavepointRestoreOperation.java:149)
    at org.apache.flink.runtime.state.heap.HeapSavepointRestoreOperation.restore(HeapSavepointRestoreOperation.java:125)
    at org.apache.flink.runtime.state.heap.HeapSavepointRestoreOperation.restore(HeapSavepointRestoreOperation.java:57)
    at org.apache.flink.runtime.state.heap.HeapKeyedStateBackendBuilder.restoreState(HeapKeyedStateBackendBuilder.java:169)
    ... 20 more
Caused by: java.lang.IndexOutOfBoundsException: Index 83 out of bounds for length 3
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Unknown Source)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Unknown Source)
    at java.base/jdk.internal.util.Preconditions.checkIndex(Unknown Source)
    at java.base/java.util.Objects.checkIndex(Unknown Source)
    at java.base/java.util.ArrayList.get(Unknown Source)
    at com.esotericsoftware.kryo.util.MapReferenceResolver.getReadObject(MapReferenceResolver.java:42)
    at com.esotericsoftware.kryo.Kryo.readReferenceOrNull(Kryo.java:805)
    at com.esotericsoftware.kryo.Kryo.readObjectOrNull(Kryo.java:728)
    at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:113)
    ... 31 more

I expected this exception would be thrown for io.peleg.kryo.User since Flink does not support state schema evolution for Kryo serialized classes.我预计io.peleg.kryo.User会抛出这个异常,因为 Flink 不支持 Kryo 序列化类的状态模式演变。

But it seems to me like for all classes it ended up using the Kryo serializer instead of the POJO or Avro serializers.但在我看来,所有类最终都使用 Kryo 序列化程序而不是 POJO 或 Avro 序列化程序。

I ran the job on a Flink cluster I spun up using docker compose:我在使用 docker compose 启动的 Flink 集群上运行了这项工作:

version: "2.2"
services:
  jobmanager:
    image: flink:latest
    ports:
      - "8081:8081"
    command: jobmanager
    environment:
      - |
        FLINK_PROPERTIES=
        jobmanager.rpc.address: jobmanager

  taskmanager:
    image: flink:latest
    depends_on:
      - jobmanager
    command: taskmanager
    scale: 1
    environment:
      - |
        FLINK_PROPERTIES=
        jobmanager.rpc.address: jobmanager
        taskmanager.numberOfTaskSlots: 2

My entire code is public on GitHub here .我的整个代码在 GitHub 上是公开

What I would like to achieve is succusfuly running a job from a savepoint of an older version of a POJO with less/more fields.我想要实现的是从具有更少/更多字段的旧版本 POJO 的保存点成功运行作业。

I did an experiment with this POJO class:我对这个 POJO 类做了一个实验:

public class Event {

    public long id;
    public String data;
    public Instant timestamp;

    public Event() {}

    public Event(final long id, final String data, final Instant timestamp ) {
        this.id = id;
        this.data = data;
        this.timestamp = timestamp;
    }

    ...
}

The image below is from the IntelliJ debugger.下图来自 IntelliJ 调试器。 As you can see, Flink supplied an InstantSerializer , and is using its POJOSerializer for this Event class.如您所见,Flink 提供了一个InstantSerializer ,并将其POJOSerializer用于该Event类。

在此处输入图像描述

I'm not sure where you went wrong, but you can use我不确定你哪里出错了,但你可以使用

env.getConfig().disableGenericTypes();

to disable the Kyro fallback, which should help with these experiments.禁用 Kyro 后备,这应该有助于这些实验。

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

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