Flink--Souce(自定义)

本文介绍了如何在Apache Flink中自定义SourceFunction,以解决实际场景下数据不足或数据源访问问题。通过实例展示了如何创建一个模拟温度传感器数据的SourceFunction,包括数据生成、偏移模拟和不间断发送过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自定义Source

使用自定义的Source具体可以用在以下两个场景:

  1. 系统以及开发好了,但是没有足够数量的数据
  2. 没有具体的实现方法到数据源去读取数据
    此时就需要我们去实现一个自定义Sources

实现自定义Sources

需要:模拟温度传感器产生的数据

当所需sourceFunciton没有具体实现时,需要自定义:

class mySource() extends SourceFunction[SensorReading]{}

这里SourceFunction[T] 中传入的泛型为要发出参数的类型:
首先SourceFunction把这个泛型T传给 SourceContext [T],
然后再 SourceContext 的collet方法中发现 传入泛型T并把结果发送了出去

所以这里泛型设置为 SensorReading

因为SourceFunction是抽象类,所以要重写父类方法

cancel: 用于控制停止发送数据
run:生产或者读取数据 并通过SourceContext.collect发送出去。

Cancel

定义一个flag用于标识是否发送数据,然后当调用cancel就使其false

var running:Boolean = true
override def cancel(): Unit = running = false

Run

这里首先产生十个温度传感器的初始值

 val random = new Random()
    //获取初始数据
    val originData = 1.to(10).map(data => ("Sensor_"+data,random.nextDouble() * 100))

然后再初始值上加上高思函数偏移量用于模拟真实环境

val mapedData = originData.map(data => (data._1,data._2 + random.nextGaussian()))

然后保证成SensorReading类型发送出去

//获取时间戳
      val timeStamp = System.currentTimeMillis()

//发出数据
mapedData.foreach(data =>sourceContext.collect(SensorReading(data._1,timeStamp,data._2)))

因为需要源源不断发送,所以添加循环

override def run(sourceContext: SourceFunction.SourceContext[SensorReading]): Unit = {

    val random = new Random()
    //获取初始数据
    val originData = 1.to(10).map(data => ("Sensor_"+data,random.nextDouble() * 100))

    while(running){

    //添加偏移量
    val mapedData = originData.map(data => (data._1,data._2 + random.nextGaussian()))

    //获取时间戳
    val timeStamp = System.currentTimeMillis()

    //发出数据
    mapedData.foreach(data =>sourceContext.collect(SensorReading(data._1,timeStamp,data._2)))

    //添加睡眠时间
    Thread.sleep(100)
    }

完整代码

package com.erke

import org.apache.flink.streaming.api.functions.source.SourceFunction
import org.apache.flink.streaming.api.scala._

import scala.util.Random


case class SensorReading(id:String,timeStamp:Long,temperature:Double)

class mySource() extends SourceFunction[SensorReading]{
  var running:Boolean = true
  override def cancel(): Unit = running = false

  override def run(sourceContext: SourceFunction.SourceContext[SensorReading]): Unit = {

    val random = new Random()
    //获取初始数据
    val originData = 1.to(10).map(data => ("Sensor_"+data,random.nextDouble() * 100))

    while(running){

      //添加偏移量
      val mapedData = originData.map(data => (data._1,data._2 + random.nextGaussian()))

      //获取时间戳
      val timeStamp = System.currentTimeMillis()

      //发出数据
      mapedData.foreach(data =>sourceContext.collect(SensorReading(data._1,timeStamp,data._2)))

      //添加睡眠时间
      Thread.sleep(100)
    }
  }
}

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

    val env = StreamExecutionEnvironment.getExecutionEnvironment

    val mySouceDataStream = env.addSource(new mySource())

    mySouceDataStream.print()

    env.execute("SourceTest")
  }
}

目前官方尚未发布 Apache Flink 2.0 的正式版本,因此关于 Flink 2.0 的具体示例代码和实例教程较少公开可用。然而,可以根据现有 Flink 版本的功能推测其未来可能的方向,并结合已有的功能提供一些通用的示例。 以下是基于当前 Flink 功能的一个典型数据流处理示例: ### 数据流处理示例 假设有一个股票价格流 `stockPriceStream`,我们需要对其进行按符号 (`symbol`) 分组并计算每分钟的最大价格。 ```scala import org.apache.flink.api.common.functions.AggregateFunction import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment import org.apache.flink.streaming.api.windowing.time.Time import org.apache.flink.streaming.api.datastream.DataStream import org.apache.flink.streaming.api.scala._ case class StockPrice(symbol: String, price: Double) object StockMaxPrice { def main(args: Array[String]): Unit = { val env = StreamExecutionEnvironment.getExecutionEnvironment // 原始股票价格流 val stockPriceRawStream: DataStream[StockPrice] = ??? // 按照 symbol 进行 keyBy 分组 val keyedStream = stockPriceRawStream.keyBy(_.symbol)[^2] // 计算每分钟最大价格 val maxPricesPerMinute = keyedStream .timeWindow(Time.minutes(1)) .aggregate(new MaxPriceAggregate()) maxPricesPerMinute.print() env.execute("Flink Streaming Scala API Example") } // 自定义聚合函数用于计算最大价格 class MaxPriceAggregate extends AggregateFunction[StockPrice, Double, Double] { override def createAccumulator(): Double = Double.MinValue override def add(value: StockPrice, accumulator: Double): Double = Math.max(accumulator, value.price) override def getResult(accumulator: Double): Double = accumulator override def merge(a: Double, b: Double): Double = Math.max(a, b) } } ``` 此代码展示了如何使用 Flink 对股票价格流进行分组、窗口化以及聚合操作。其中的关键概念包括 `keyBy` 和时间窗口的应用。 --- ### 关于 Flink Connector 如果需要连接外部系统(如 Kafka 或数据库),可以利用 Flink 提供的各种内置 connector。例如,以下是一个简单的 Kafka Source 示例: ```java import org.apache.flink.api.common.serialization.SimpleStringSchema; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.connector.kafka.source.KafkaSource; public class KafkaExample { public static void main(String[] args) throws Exception { final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); KafkaSource<String> kafkaSource = KafkaSource.<String>builder() .setBootstrapServers("localhost:9092") .setTopics("input-topic") .setGroupId("test-group") .setValueOnlyDeserializer(new SimpleStringSchema()) .build(); env.fromSource(kafkaSource, WatermarkStrategy.noWatermarks(), "Kafka Source") .print(); env.execute("Flink Kafka Example"); } } ``` 上述代码片段展示了一个基本的 Kafka 数据源配置过程[^1]。 --- ### 性能优化与事务支持 Flink 支持高性能的流处理能力,具有高吞吐量、低延迟等特点[^3]。此外,在涉及事务处理时,可以通过 `transaction` 字段传递额外信息以增强系统的可靠性[^4]。 尽管这些特性并非特定针对 Flink 2.0 设计,但它们代表了现代流处理框架的核心需求和发展方向。 --- ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值