[英]Flink schema evolution not working for broadcast state
我在 flink 中使用广播 state 模式,我试图连接两个流,一个 stream 是规则的控件 stream,另一个 stream 是整数的 stream(用于虚拟播放目的)。
我有以下Rule
class
public class Rule {
String id;
int val;
RuleType ruleType;
//Newly added field
//int val2 = 0;
public Rule() {}
public Rule(String id, int val, RuleType ruleType) {
this.id = id;
this.val = val;
this.ruleType = ruleType;
//this.val2 = val2;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
public RuleType getRuleType() {
return ruleType;
}
public void setRuleType(RuleType ruleType) {
this.ruleType = ruleType;
}
//public int getVal2() {
// return val2;
//}
//public void setVal2(int val2) {
// this.val2 = val2;
//}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Rule rule = (Rule) o;
return val == rule.val && id.equals(rule.id) && ruleType == rule.ruleType;
}
@Override
public int hashCode() {
return Objects.hash(id, val, ruleType);
}
@Override
public String toString() {
return "Rule{" +
"name='" + id + '\'' +
", val=" + val +
", ruleType=" + ruleType +
'}';
}
}
这是规则类型 class
public enum RuleType {
X,
Y,
Z
}
在BroadcastState
中,我正在存储List<Rule> ruleList;
. 如文档中所述,我尝试按照以下步骤检查架构演变是否适用于此:
启动flink集群
提交工作 jar
使用flink savepoint <jobId>
命令获取一个保存点。
停止工作。
修改代码,在Rule class中增加一个int
字段val2
,如上图。 新建一个 jar。
尝试使用flink -s <savepoint>
命令恢复作业。
使用此作业无法重新启动,因为模式演变失败并出现以下错误:
由以下原因引起:org.apache.flink.util.FlinkException:无法从提供的任何 1 个恢复选项中恢复 CoBroadcastWithNonKeyedOperator_8c5504f305beefca0724b3e55af8ea26_(1/1) 的运算符 state 后端。 at org.apache.flink.streaming.api.operators.BackendRestorerProcedure.createAndRestore(BackendRestorerProcedure.java:160) at org.apache.flink.streaming.api.operators.StreamTaskStateInitializerImpl.operatorStateBackend(StreamTaskStateInitializerImpl.java:286) at org.apache .flink.streaming.api.operators.StreamTaskStateInitializerImpl.streamOperatorStateContext(StreamTaskStateInitializerImpl.java:174)... 11 more Caused by: org.apache.flink.runtime.state.BackendBuildingException: Failed when trying to restore operator state backend at org. apache.flink.runtime.state.DefaultOperatorStateBackendBuilder.build(DefaultOperatorStateBackendBuilder.java:83) at org.apache.flink.runtime.state.hashmap.HashMapStateBackend.createOperatorStateBackend(HashMapStateBackend.java:148) at org.apache.flink.streaming.api.操作 erators.StreamTaskStateInitializerImpl.lambda$operatorStateBackend$0(StreamTaskStateInitializerImpl.java:277) 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: Unable to find class: 11 at com.esotericsoftware.kryo.util.DefaultClassResolver.readName(DefaultClassResolver.java: 138) 在 com.esotericsoftware.kryo.util.DefaultClassResolver.readClass(DefaultClassResolver.java:115) 在 com.esotericsoftware.kryo.Kryo.readClass(Kryo.java:641)
有人可以帮忙吗? 我怀疑规则 class 出于某种原因没有被 POJO 序列化程序使用,但我不明白为什么? 它遵循成为 POJO 的所有标准。
这是我经过大量研究后找到的答案。 Flink 文档在提供示例方面确实很糟糕,因此这可能会帮助其他人解决同样的问题。
我能够为这个 class 创建我自己的 TypeInfoFactory,如下所示:
public static class MyPojoTypeInfoFactoryForRule extends TypeInfoFactory<Rule> {
@Override
public TypeInformation<Rule> createTypeInfo(
Type t, Map<String, TypeInformation<?>> genericParameters) {
Map<String, TypeInformation<?>> fields =
new HashMap<String, TypeInformation<?>>() {
{
put("id", Types.STRING);
put("val", Types.INT);
put("ruleType", Types.ENUM(RuleType.class));
put("val2", Types.INT);
}
};
return Types.POJO(Rule.class, fields);
}
}
然后用这个工厂注解Rule class,这样Rule class就被序列化为一个POJO。
悬而未决的问题是,如何让它变得更好? 我可以只为枚举 class 而不是整个规则 class 编写工厂吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.