4、如何在flink任务中读取外部数据源(DataStream API)

1、Flink读取外部数据源的方式

Flink是一个流批一体的分布式计算框架,它不会存储数据,编写Flink计算任务的第一步就是通过连接器去读取外部数据

Flink提供了多种`预定义 data sources` 来读取外部数据,如 文件、目录、Socket、集合、Kafka等外部数据源,另外也是要通过自定义数据源来读取外部数据


2、数据源的类型 

Flink 中读取的数据源,根据知否支持切片,分为 非并行数据源 和 并行数据源 两大类

           并行数据源      :  可以将数据源拆分成多个 子任务,并行执行( 并行度允许大于1)

        非并行数据源     :    不可以将数据源拆分,只能有单独的任务处理数据 (并行度必须1)    

我们可以通过 StreamExecutionEnvironment.addSource(SourceFunction) 将一个 source对象 关 联到编写的 flink应用程序中
        Flink API中 自带了许多 SourceFunction的实现类

        我们也可以 通过实现 SourceFunction接口 来编写 自定义的非并行的source对象
                           通过实现 ParallelSourceFunction 接口
                                  继承 RichParallelSourceFunction 类 来编写 自定义的并行source对象


3、Flink 中的数据类型(TypeInformation)

Flink 会将外部的数据加载到 DataStreamSource 对象中,加载过程中会将外部的数据的类型转换为 Flink 定义的数据类型

为了方便 数据序列化和反序列化,Flink定义了自己的数据类型系统


4、从集合中读取数据

Flink任务怎样读取集合中的数据


5、从文件中读取数据

Flink任务怎样读取文件中的数据


6、从Socket中读取数据

语法说明:

语法:
    def socketTextStream(hostname: String, port: Int, delimiter: Char = '\n', maxRetry: Long = 0):
        DataStream[String] =
    asScalaStream(javaEnv.socketTextStream(hostname, port))
功能:
    执行监控,socket中的文本流,按行读取数据(默认分隔符为 \n)
参数:
    hostname : socket服务ip
    prot     : socket服务端口号
    Char     : 行分隔符
    maxRetry : 当 socket服务 停止时,flink程序 重试连接时间(单位为秒)
               =0 时,表示 连接不到 socket服务后,立刻停止 flink程序
               =-1 时,表示 永远保持重试连接
tips:
    scala API 只提供了一种 socketTextStream方法的实现
    如果想使用其他参数,需要使用java api

代码示例:

package com.baidu.datastream.source;

import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

// --------------------------------------------------------------------------------------------
//  TODO 从Socket中读取数据
// --------------------------------------------------------------------------------------------

/*
 *  TODO socketTextStream(hostname: String, port: Int, delimiter: String, maxRetry: Long)
 *  功能说明:
 *       包含从套接字接收到的字符串的数据流
 *  参数说明:
 *       @hostname  : 指定ip
 *       @port      : 指定端口号
 *       @delimiter : 指定元素分隔符(默认为\n)
 *       @maxRetry  :  指定连接失败时,重试连接的时间间隔(以秒为单位)
 *                     默认为为0,表示连接失败时,程序立即终止
 *                     负值时,表示一直重试连接
 * */

public class ReadSocket {
    public static void main(String[] args) throws Exception {
        // 1.获取执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        // 2.将socket作为数据源(开启socket端口: nc -lk 9999)
        env.socketTextStream("localhost", 9999).print();

        // 3.触发程序执行
        env.execute();
    }
}

7、从Kafka中读取数据

传送门:Flink任务怎样读取Kafka中的数据


8、从DataGen中读取数据

传送门:从DataGen中读取数据


9、自定义数据源

9.1 自定义非并行数据源

 代码示例:

/*
* TODO 自定义非并行数据源
*    实现步骤:
*        1.实现 SourceFunction接口
*        2.实现 run方法
*           调用 collect方法 发送数据
*        3.实现 cancel方法
*   注意事项:
*        1.接口的泛型为 数据源的数据类型
* */
class CustomNonParallelSource extends SourceFunction[String] {
  // 标志位,用来控制循环的退出
  var isRunning = true

  override def run(ctx: SourceFunction.SourceContext[String]): Unit = {
    val list = List("刘备1", "关羽2", "张飞3", "赵云4", "马超5")

    while (isRunning) {
      // 调用 collect 方法向下游发送数据
      list.foreach(
        e => {
          ctx.collect(e)
          Thread.sleep(1000)
        }
      )

    }

  }

  // 通过将 isRunning 设置为false,来终止消息的发送
  override def cancel(): Unit = isRunning = false
}

  /*
  * TODO 从 自定义数据源中 读取数据
  *
  * */
  test("从 自定义非并行数据源中 读取数据") {

    // 1. 获取流执行环境
    val env = StreamExecutionEnvironment.getExecutionEnvironment

    // 2. 将 自定义数据源 作为数据源
    val ds: DataStream[String] = env.addSource(new CustomNonParallelSource).setParallelism(1)

    // 3. 打印DataStream
    ds.print().setParallelism(1)

    // 4. 出发程序执行
    env.execute()
  }

执行结果:

9.2 自定义并行数据源

代码示例:

/*
* TODO 自定义并行数据源
*    实现步骤:
*        1.实现 ParallelSourceFunction接口 或者 继承RichParallelSourceFunction
*        2.实现 run方法
*           调用 collect方法 发送数据
*        3.实现 cancel方法
*   注意事项:
*        1.接口的泛型为 数据源的数据类型
* */
class CustomParallelSource extends RichParallelSourceFunction[String] {
  // 标志位,用来控制循环的退出
  var isRunning = true

  override def run(ctx: SourceFunction.SourceContext[String]): Unit = {
    val list = List("刘备1", "关羽2", "张飞3", "赵云4", "马超5")

    while (isRunning) {
      // 调用 collect 方法向下游发送数据
      // 调用 collect 方法向下游发送数据
      list.foreach(
        e => {
          ctx.collect(e)
          Thread.sleep(1000)
        }
      )

    }
  }

  // 通过将 isRunning 设置为false,来终止消息的发送
  override def cancel(): Unit = isRunning = false
}


  test("从 自定义并行数据源中 读取数据") {

    // 1. 获取流执行环境
    val env = StreamExecutionEnvironment.getExecutionEnvironment

    // 2. 将 自定义数据源 作为数据源
    val ds: DataStream[String] = env.addSource(new CustomParallelSource).setParallelism(4)

    // 3. 打印DataStream
    ds.print().setParallelism(1)

    // 4. 出发程序执行
    env.execute()
  }

执行结果:

9.3 使用自定义数据源读取MySQL

传送门:使用自定义源算子读取MySQL


10、addSource 还是 fromSource

fromSource是flink1.17在新的Data Source 架构上提供的API,较旧的 addSource 最大的区别就是

fromSource  允许在调用的时候指定`提取时间戳&添加水位线`

// newAPI:在调用 fromSource 时,指定水位线生成策略
public <OUT> DataStreamSource<OUT> fromSource(
        Source<OUT, ?, ?> source,
        WatermarkStrategy<OUT> timestampsAndWatermarks,
        String sourceName) {
    return fromSource(source, timestampsAndWatermarks, sourceName, null);
}

// oldAPI:在生成 DataStreamSource 后 在调用 assignTimestampsAndWatermarks,添加水位线生成策略
public <OUT> DataStreamSource<OUT> addSource(SourceFunction<OUT> function, String sourceName) {
    return addSource(function, sourceName, null);
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值