Flink-將DataStream 轉換成表 | 創建臨時視圖 | 輸出到文件 | 輸出到Kafka | 更新模式

GitHub

https://github.com/SmallScorpion/flink-tutorial.git

將 DataStream 轉換成表

Flink允許我們把Table和DataStream做轉換:我們可以基於一個DataStream,先流式地讀取數據源,然後map成樣例類,再把它轉成Table。Table的列字段(column fields),就是樣例類裏的字段,這樣就不用再麻煩地定義schema了。

import com.atguigu.bean.SensorReading
import org.apache.flink.streaming.api.scala._
import org.apache.flink.table.api.{DataTypes, Table}
import org.apache.flink.table.api.scala._

object DataStreamToTableTest {
  def main(args: Array[String]): Unit = {

    val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
    env.setParallelism(1)

    // 創建表環境
    val tableEnv: StreamTableEnvironment = StreamTableEnvironment.create(env)

    val inputDStream: DataStream[String] = env.readTextFile("D:\\MyWork\\WorkSpaceIDEA\\flink-tutorial\\src\\main\\resources\\SensorReading.txt")

    val dataDstream: DataStream[SensorReading] = inputDStream.map(
      data => {
        val dataArray: Array[String] = data.split(",")
        SensorReading(dataArray(0), dataArray(1).toLong, dataArray(2).toDouble)
      })

    // 常規創建
    val dataTable: Table = tableEnv.fromDataStream(dataDstream)
    // Schema基於名稱
    val sensorTable = tableEnv.fromDataStream(dataDstream,
      'timestamp as 'ts, 'id as 'myId, 'temperature)
    // Schema基於位置 一一對應
    val sensorTable_lo = tableEnv.fromDataStream(dataDstream, 'myId, 'ts)


    // 測試輸出
    val resultTable: Table = dataTable
      .select('id, 'temperature) // 查詢id和temperature字段
      .filter('id === "sensor_1") // 輸出sensor_1得數據

    resultTable.toAppendStream[ (String, Double) ].print( "data" )


    env.execute(" table DS test job")
  }
}

在這裏插入圖片描述
在這裏插入圖片描述

創建臨時視圖(Temporary View)

View和Table的Schema完全相同。事實上,在Table API中,可以認爲View和Table是等價的。

創建臨時視圖的第一種方式,就是直接從DataStream轉換而來。同樣,可以直接對應字段轉換;也可以在轉換的時候,指定相應的字段。

tableEnv.createTemporaryView("sensorView", dataStream)
tableEnv.createTemporaryView("sensorView", dataStream, 'id, 'temperature, 'timestamp as 'ts)

還可以基於Table創建視圖:

tableEnv.createTemporaryView("sensorView", sensorTable)

輸出表

  1. 表的輸出,是通過將數據寫入 TableSink 來實現的
  2. TableSink 是一個通用接口,可以支持不同的文件格式、存儲數據庫和消息隊列
  3. 輸出表最直接的方法,就是通過 Table.insertInto() 方法將一個 Table 寫入註冊過的 TableSink 中
tableEnv.connect(...)     
	.createTemporaryTable("outputTable")
val resultSqlTable: Table = ...
resultTable.insertInto("outputTable")

輸出到文件

import org.apache.flink.streaming.api.scala._
import org.apache.flink.table.api.{DataTypes, Table}
import org.apache.flink.table.api.scala._
import org.apache.flink.table.descriptors.{FileSystem, OldCsv, Schema}

object SinkToFileSystemTest {
  def main(args: Array[String]): Unit = {

    val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
    env.setParallelism(1)

    // 創建表環境
    val tableEnv: StreamTableEnvironment = StreamTableEnvironment.create(env)

    // --------------------- 讀取文件數據 ---------------------------
    val filePath = "D:\\MyWork\\WorkSpaceIDEA\\flink-tutorial\\src\\main\\resources\\SensorReading.txt"

    tableEnv.connect( new FileSystem().path(filePath) ) // 定義表的數據來源,和外部系統建立連接
      .withFormat( new OldCsv() ) // 定義從外部文件讀取數據之後的格式化方法
      .withSchema( new Schema() // 定義表結構
        .field("id", DataTypes.STRING())
        .field("timestamp", DataTypes.BIGINT())
        .field("temperature", DataTypes.DOUBLE())
      )
      .createTemporaryTable( "fileInputTable" ) // 在表環境中註冊一張表(創建)


    val sensorTable: Table = tableEnv.from( "fileInputTable" )
    val resultTable: Table = sensorTable
      .select('id, 'temperature) // 查詢id和temperature字段
      .filter('id === "sensor_1") // 輸出sensor_1得數據

    resultTable.toAppendStream[ (String, Double) ].print( "FileSystem" )


    env.execute(" table connect fileSystem test job")
  }
}

在這裏插入圖片描述

輸出到Kafka

除了輸出到文件,也可以輸出到Kafka。我們可以結合前面Kafka作爲輸入數據,構建數據管道,kafka進,kafka出。

import org.apache.flink.streaming.api.scala._
import org.apache.flink.table.api.{DataTypes, Table}
import org.apache.flink.table.api.scala._
import org.apache.flink.table.descriptors.{Csv, Kafka, Schema}

object SinkToKafkaTest {
  def main(args: Array[String]): Unit = {

    val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
    env.setParallelism(1)

    // 創建表環境
    val tableEnv: StreamTableEnvironment = StreamTableEnvironment.create(env)

    // --------------------- 消費Kafka數據 ---------------------------

    tableEnv.connect( new Kafka()
      .version( "0.11" ) // 版本
      .topic( "sensor" ) // 主題
      .property("zookeeper.connect", "hadoop102:2181")
      .property("bootstrap.servers", "hadoop102:9092")
    )
      .withFormat( new Csv() ) // 新版本得Csv
      .withSchema( new Schema()
        .field("id", DataTypes.STRING())
        .field("timestamp", DataTypes.BIGINT())
        .field("temperature", DataTypes.DOUBLE())
      )
      .createTemporaryTable( "kafkaInputTable" )

    // 查詢
    val sensorTable: Table = tableEnv.from( "kafkaInputTable" )
    val resultTable: Table = sensorTable
      .select('id, 'temperature) // 查詢id和temperature字段
      .filter('id === "sensor_1") // 輸出sensor_1得數據

    // 定義輸出的Kafka結構
    tableEnv.connect( new Kafka()
      .version( "0.11" ) // 版本
      .topic( "sensor_out" ) // 主題
      .property("zookeeper.connect", "hadoop102:2181")
      .property("bootstrap.servers", "hadoop102:9092")
    )
      .withFormat( new Csv() ) // 新版本得Csv
      .withSchema( new Schema()
        .field("id", DataTypes.STRING())
        .field("temperature", DataTypes.DOUBLE())
      )
      .createTemporaryTable( "kafkaOutputTable" )

    // 查詢結果輸出到Kafka中
    resultTable.insertInto("kafkaOutputTable")

    env.execute(" kafka pipeline test job")
  }
}

更新模式(Update Mode)

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章