一、Flink类型管理体系简介
Flink使用一套独有的类型管理体系(结合反射机制)来管理不同task之间进行计算、传输和存储的数据的类型。
其中主要使用TypeInformation类的类族来记录和描述数据的类型信息:
在TypeInfomation中,主要将Flink处理的数据分为以下四种类型:
1.基本类型:Java中的基本类型(int,double)以及封装的(Integer,Double)和void,String,Date,BigDecimal等类型
2.基本数据类型或对象的序列(我理解为数组等)
3.复杂数据类型
- Flink中的Java的Tuple类型 不支持空值
- Scala中的Tuple等数据类型
- Row 支持有多个字段的Tuple类型
- POJO 符合java Bean 命名模式的规范的java对象
- Auxiliary types List Map等类型
- 带有泛型的数据类型
每个具体的数据类型都对应的一个具体的TypeInfomation的实现类,它记录的了数据对象具体属于以上哪一种数据类型、包含的字段数目、类的class 以及对象的序列化、反序列方式等信息。
重要:其中主要通过 createSerializer()方法获取对数据进行序列化和反序列化操作的对象。
构造一个对象的TypeInformation主要通过TypeInformation类的以下两个静态方法:
TypeInformation.of(Class<T> typeClass) 构造不包含泛型的数据类型的TypeInformation
TypeInformation.of(TypeHint<T> typeHint) 构造包含泛型的数据类型的TypeInformation
其中,TypeHint主要针对包含泛型的数据,用于记录的描述数据类型并构造对应的TypeInformation。当需要被序列化和反序列化的数据中不包含泛型时,直接根据[Type.class]就可以构造TypeInformation以及对应的Serializer,当数据包含泛型时,必须先构造对应的TypeHint,在由TypeHint获取对应的TypeInformation。
这里需要引入一个TypeExtractor的概念,该类为一个工具类,其主要功能是根据传入的数据类型信息(class或TypeHint),通过反射机制决定创建一种具体的TypeInformation以及Deserializer,其具体的实现逻辑在createTypeInfoWithTypeHierarchy()方法中,该方法根据传入的Type,依次检查数据对象属于哪一种类型,并构建一种具体的TypeInformation的实现,注入一种Deserializer。
接下来,以typeClass的方式为例介绍整个类型管理体系构建的流程:客户端代码通过TypeInformation的静态方法TypeInformation.of(Class<T> typeClass)构建数据类型对应的TypeInformation的某一种具体实现。在of()方法中实际调用TypeExtractor.createTypeInfo(typeClass)方法,通过一系列的方法调用最终到createTypeInfoWithTypeHierarchy()方法中,该方法的类型判断大致可分为以下几种类型:
- 在TypeFactory已经注册过的类型,则直接通过TypeFactory获取对应的TypeInfoamtion以及Deserializer (TypeFactory的使用方法和实现逻辑还需要深入看一下,目前知道它与Flink的配置有关)
- 当数据类型为Tuple类的子类型时,直接构建TupleTypeInfo并对应TupleSerializer