(三)flink的Table API 与 SQL-外部连接器


flink可以通过table connector直接连接外部系统,将批量或者流式数据从外部系统中获取Flink系统中,或者Flink系统中将数据发送到外部系统中,主要目的是将内建的TableSource和TableSink封装,形成可配置化的组件,在TableAPI和SQL Client能够同时使用
Table API 通过Table COnnector注册TableSource所涵盖的步骤,其中

connector

指定了需要连接table connector对应的Descriptor

withFormat

指定了输出或输入的文件格式,例如JSON或parquet等

withSchema

指定注册在Table Environment中的表结构

InAppendMode

指定了数据更新模式,

registerTable Source

将本次连接的数据源对应的TableSource注册在TableEnvironment中

tableEnviroment
		.connect(...)		//指定Table Connector Descriptor
		.withFormat(...)	//指定数据格式
		.withSchema(...)	//指定表结构
		.inAppendMode()		//指定更新模式
		.registerTableSource("MyTable")		//注册TableSource

Table Source

Table API和SQL中使用 org.apache.flink.table.descriptors.Descriptor 接口实现类来创建Table Connector实例,在Flink内置的Table Connector有File System Connector,KafkaConnector ,以及 ES Connector等

(1)File System Connector

允许用户从本地文件或者分布式文件系统中读取和写入数据,在Table API中文件系统的Table Connector可以通过FileSystem类来创建,只需要指定相应的参数即可

    val env = StreamExecutionEnvironment.getExecutionEnvironment
    val tabEnv = StreamTableEnvironment.create(env)
    tabEnv.connect(
      new FileSystem()
        .path("") //可以是文件夹或文件
    )

(2) Kafka Connector

Kafka Connector支持从Kafka中消费和写入数据

    tabEnv.connect(
      new Kafka()
        .version("0.11")  //指定Kafka的版本,支持0.8,0.9,0.10,0.11
        .topic("") // 指定topic信息
        .property("zookeeper.connect","")
        .property("bootstrap.servers","")
        .property("group.id","")
        //从kafka中读取数据: 指定offset的启动模式(可选)
        .startFromEarliest() //从最早的offset开始消费
        .startFromLatest()  //从最新的offset开始消费
//        .startFromSpecificOffset(...)  //从指定的offset开始消费
      //向kafka中写入数据,指定Flink和Kafka的数据分区策略
        .sinkPartitionerFixed() //每个Flink分区最多被分配到一个kafka分区上
        .sinkPartitionerRoundRobin()  //flink中分区随机映射到Kafka分区上
        .sinkPartitionerCustom(xxx.class) //自定义KafkaPartitioner
    )

对于端到端的一致性保障,默认kafka的table connector支持到at-least-once级别,同时flink提供exactly-once级别的一致性保障,前提需要集群打开CheckPointing功能

Table Format

Flink中提供了常用的Table Format,可以在Table Connector中使用,支持Connector 传输不同格式类型不同格式的数据,例如CSV,JSON,Avro等,通过withFormat方法指定

(1) CSV Format

CSV Format指定分隔符切分数据记录中字段,可以使用field字段来指定字段名称和类型,使用fieldDelimiter方法来指定切割符,使用lineDelimiter来指定行切割符
需要引入依赖

<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-csv</artifactId>
    <version>1.9.1</version>
</dependency>

     .withFormat(
        new Csv()
          .field("field1", Types.STRING)    // 根据顺序字段指明字段名以及类型  (必选)
          .field("field2", Types.INT())
          .fieldDelimiter(",")              // 列切割符 (可选)
          .lineDelimiter("\n")              // 行切割符 (可选)
          .quoteCharacter('"')              // 指定字符串中单个字符,默认为空 (可选)
          .commentPrefix('#')               // 指定comment的前缀,默认为空 (可选)
          .ignoreFirstLine()                // 可忽略第一行 (可选)
          .ignoreParseErrors()              // 是否忽略解析错误的数据,默认开启(true)
      )

(2)JSON Format

JSON Format 支持读取或写入的数据映射成JSON格式,在Table API中JSON Format具有三种定义方式,通过Flink数据类型定义,直接使用JSON Schema定义,将Flink Table Schema转换成JSON Schema的方式来定义,其中,JSON Schema能够定义非常复杂和嵌套的数据结构,而flink内部数据类型定义比较适合简单的Mapping关系,Flink会根据映射关系将Table中的数据类型转换成JOSN格式.如FLink中Row类型对应JSON中的object结构,String类型对应于JSON中的VARCHAR结构等,如果Flink Table Schema信息和JSON的Schema一致,则可以直接使用deriveShema从table中抽取JSON Schema信息,使用这种方式,用户只需定义一Table Schema,字段名称,类型,位置都是由Table Schema确定的

   .withFormat(
        new Json()
          .failOnMissingField(true)   //当字段缺失的时候是否解析失败(可选)
          //[方式一:] 使用Flink数据类型定义,然后通过Mapping映射成JSON Schema
          .schema(Types.ROW(...))
         //[方式二:] 通过配置jsonSchema构建JSON Format 
      .jsonSchema(
        """
          |{
          |type:'object',
          |properties:{
          |id:{
          |type:'number',
          |},
          |name:{
          |type:'string',
          |},
          |rowtime:{
          |type:'string',
          |format:'date-time'
          |}
          |}
          |}
          |""".stripMargin)
          //[方式三:] 直接使用Table中的Schema信息,转换成JSON结构
          .deriveSchema()
      )

Flink只支持object,array,number等常用的JSON Schema的子集数据类型,不支持类似于allof,anyOf,not等复杂JSON数据结构

(2)Apache Avro Format

支持读取和写入Avro格式数据,和JSON Format一样,Avro Format数据具有丰富的数据结构类型,以及快速可压缩的二进制数据形式,Avro Format结构可以通过定义Avro的SpecificRecord Class来实现.或者通过指定avroSchema的方式来定义

      .withFormat(
        new Avro()
          //(1):通过avro SpecificRecord Class来实现
//          .recordClass(xxx.class)
          //(2):通过avroSchema字符串定义
      .avroSchema(
        """
          | {
          |   "type":"record",
          |   "name":"envent",
          |   "field":[
          |   {"name":"id","type":"long"},
          |   {"name":"name","type":"string"}
          |   ]
          | }
          |""".stripMargin)
      )
发布了483 篇原创文章 · 获赞 62 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/wwwzydcom/article/details/103749927