StructuredStreaming的多种数据源详解

简介: 从Spark 2.0至Spark 2.4版本,目前支持数据源有4种,其中Kafka 数据源使用作为广泛,其他数据源主要用于开发测试程序。
在这里插入图片描述
在这里插入图片描述

1. Socket数据源

  • 用nc -lk 端口号向Socket监听的端口发送数据,用于测试使用:
    1.host
    2.port 参数
    在这里插入图片描述

  • Console 接收器在这里插入图片描述
    在这里插入图片描述

代码:

import org.apache.commons.lang3.StringUtils
import org.apache.spark.SparkConf
import org.apache.spark.sql.streaming.{
    
    OutputMode, StreamingQuery, Trigger}
import org.apache.spark.sql.{
    
    DataFrame, Dataset, Row, SparkSession}


/**
 * @author liu a fu
 * @date 2021/1/25 0025
 * @version 1.0
 * @DESC Structured Streaming模拟Socket初体验
 *       1-初始化SParkSession
 *       2-读取数据源
 *       3-FlatMap
 *       4-gruopBy
 *       5-count
 *       6-orderby
 *       7-将结果写入
 */
object _01StructuredAndSocket {
    
    
  def main(args: Array[String]): Unit = {
    
    
    //1-环境准备
    val conf: SparkConf = new SparkConf()
      .setAppName(this.getClass.getSimpleName.stripSuffix("$"))
      .setMaster("local[6]")

    val spark: SparkSession = SparkSession
      .builder()
      .config(conf)
      //注意如果默认情况下SparkSQL发生shuffle的分区个数为200个,这里设置分区个数小一些
      .config("spark.sql.shuffle.partitions", 2)
      .getOrCreate()
    spark.sparkContext.setLogLevel("WARN")

    import spark.implicits._

    //2-读取数据源
    // Returns a `DataStreamReader` that can be used to read streaming data in as a `DataFrame`.
    val reviceData: DataFrame = spark
      .readStream
      .format("socket")
      .option("host", "node1")
      .option("port", 9999)
      .load()

    //reviceData.printSchema()
    //root
    // |-- value: string (nullable = true)

    //3-FlatMap-注意这里的DataFrame不能直接使用split的方法,不知道泛型类型 DataFrame--->DataSet 做一个as[String]类型转换
    //4-gruopBy
    //5-count
    //6-orderby
    val valueDF: Dataset[Row] = reviceData
      .as[String]
      .filter(x => StringUtils.isNoneBlank(x))
      .flatMap(_.split("\\s+"))
      .groupBy($"value")
      .count()
      .orderBy($"count".desc)


    //7-将结果写入
    //.printSchema()
    //root
    // |-- value: string (nullable = true)
    // |-- count: long (nullable = false)
    val query: StreamingQuery = valueDF.writeStream
      .format("console") //写入控制台

      //Complete完全显示模式
      //Append追加模式,显示更新的数据
      //Update更新的方式显示数据
      //- append:默认的追加模式,将新的数据输出!只支持简单查询,如果涉及的聚合就不支持了
      //- complete:完整模式,将完整的数据输出,支持聚合和排序
      //- update:更新模式,将有变化的数据输出,支持聚合但不支持排序,如果没有聚合就和append一样
      .outputMode(OutputMode.Complete()) //Complete完全,无论是否更新全部显示,能够用于有聚合有排序的场景
      .option("numRows", 10)
      .option("truncate", false)
      //这里ProcessingTime和ContinueTime两个时间一个时间是数据处理的时间-连续时间
      .trigger(Trigger.ProcessingTime(0)) //设置0  尽可能快的处理
      //Starts the execution of the streaming query
      .start()

    query.awaitTermination() //等待任意的异常发生程序结束
    query.stop()


  }

}

2. 文件数据源(了解)

  • 将目录中写入的文件作为数据流读取,支持的文件格式为:text、csv、json、orc、parquet
import org.apache.spark.SparkConf
import org.apache.spark.sql.streaming.{
    
    OutputMode, StreamingQuery, Trigger}
import org.apache.spark.sql.{
    
    DataFrame, Dataset, Row, SparkSession}
import org.apache.spark.sql.types.{
    
    DataTypes, StructType}

/**
 * @author liu a fu
 * @date 2021/1/25 0025
 * @version 1.0
 * @DESC Structured Streaming实时读取本地数据源文件   文件数据源
 */
object _01StrecturedFileLocal {
    
    
  def main(args: Array[String]): Unit = {
    
    
    //1-环境的初始化
    val conf: SparkConf = new SparkConf()
      .setAppName(this.getClass.getSimpleName.stripSuffix("$"))
      .setMaster("local[*]")
      .set("spark.sql.streaming.checkpointLocation", "path")
    val spark: SparkSession = SparkSession
      .builder()
      .config(conf)
      //注意如果默认情况下SparkSQL发生shuffle的分区个数为200个,这里设置分区个数小一些
      .config("spark.sql.shuffle.partitions", 2)
      .getOrCreate()

    spark.sparkContext.setLogLevel("WARN")
    import spark.implicits._

    //2-读取数据源文件
    val schema: StructType = new StructType()
      .add("name", DataTypes.StringType, true)
      .add("age", DataTypes.DoubleType, true)
      .add("hobby", DataTypes.StringType, true)

    val reviceDF: DataFrame = spark.readStream
      .format("csv")
      .option("sep", ";")    //按照什么切分
      .option("header", false)
      .schema(schema)
      .load("data/input/structured")
    //reviceDF.printSchema()
    //root
    // |-- name: string (nullable = true)
    // |-- age: double (nullable = true)
    // |-- hobby: string (nullable = true)

    //3-具体业务
      //统计统计年龄小于25岁的爱好 并排序
    val resultDS: Dataset[Row] = reviceDF
      .filter($"age" < 25)
      .groupBy($"hobby")
      .count()
      .orderBy($"count".desc)

    //3-FlatMap
    //4-gruopBy
    //5-count
    //6-orderby

    //4-将结果写入
    val query: StreamingQuery = resultDS
      .writeStream
      .format("console") //什么格式  控制台输出
      .outputMode(OutputMode.Complete()) //输出模式
      .trigger(Trigger.ProcessingTime(0)) //触发器,两个时间
      .option("numRows", 10) //几行
      .option("truncate", false) //是否截断输出
      .start() //开启执行

    query.awaitTermination() //直到有程序停止
    query.stop() //停止
  }

}

猜你喜欢

转载自blog.csdn.net/m0_49834705/article/details/113389824
今日推荐