flink自定义source与自定义sink

博客介绍了Flink的source和sink,即数据源和数据接收器。原生Flink提供的常用数据源连接器无法满足日常开发中多样的数据源和持久化工具需求,因此需使用其接口自定义source和sink,还给出了自定义MongoDB source和MySQL sink的实践。

flink自定义source与自定义sink

flink 的source和sink即数据源和数据接收器。在原生的flink中提供了一些常用的数据源连接器,但是在日常开发中我们所使用的数据源和持久化工具是多种多样的,flink提供的 source和sink就不能满足我们的需求,这时就需要使用flink提供的接口自定义source和sink。

flink 提供的source 和 sink
flink 支持的source 和 sink
自定义MongoDB source

以鸢尾花数据集作为mongodb中的数据原
鸢尾花数据集
定义一个Iris数据类做数据转换

import com.alibaba.fastjson.JSON
 
case class Iris(
                 category: String,
                 sepalLength: Double,
                 sepalWidth: Double,
                 petalLength: Double,
                 petalWidth: Double
               )  {
}

object Iris {

  def apply(jsonString: String): Iris = {
    val jobject = JSON.parseObject(jsonString)
    new Iris(jobject.getString("class"),
      jobject.getDouble("sepalLength"),
      jobject.getDouble("sepalWidth"),
      jobject.getDouble("petalLength"),
      jobject.getDouble("petalWidth"))
  }

}

自定义 Mongodb source
mongodb-driver 的pom依赖

        <dependency>
            <groupId>org.mongodb.scala</groupId>
            <artifactId>mongo-scala-driver_2.11</artifactId>
            <version>2.5.0</version>
        </dependency>
import bean.Iris
import org.apache.flink.configuration.Configuration
import org.apache.flink.streaming.api.functions.source.{RichSourceFunction, SourceFunction}
import org.mongodb.scala.{Document, MongoClient, MongoCollection, MongoDatabase}
import Helpers._
// https://github.com/mongodb/mongo-scala-driver/blob/master/examples/src/test/scala/tour/Helpers.scala
 
class MongodbSource
  extends RichSourceFunction[Seq[Iris]] {

  // mongodb url
  private val mongourl = "mongodb://root:123456@localhost:27017/admin"
  var mongoClient: MongoClient = null
  var collection: MongoCollection[Document] = null

  override def cancel(): Unit = {}

  // open() 方法中建立连接,这样不用每次 invoke 的时候都要建立连接和释放连接
  override def open(parameters: Configuration): Unit = {
    super.open(parameters)
    mongoClient = MongoClient(mongourl)
    val database: MongoDatabase = mongoClient.getDatabase("datatest")
    collection = database.getCollection("iris")

  }

 // 关闭连接
  override def close(): Unit = {
    super.close()

    if (mongoClient != null) {
      mongoClient.close()
    }
  }

  // DataStream 调用  run() 方法用来获取数据
  override def run(ctx: SourceFunction.SourceContext[Seq[Iris]]) = {
    val irises = collection.find().results()
      .map(_.toJson())
      .map(Iris.apply)

    ctx.collect(irises)

  }

}

自定义 MySQL sink


import java.sql.{Connection, DriverManager, PreparedStatement}
import bean.Iris
import org.apache.flink.configuration.Configuration
import org.apache.flink.streaming.api.functions.sink.RichSinkFunction
 
class MysqlSink extends RichSinkFunction[Iris] {

  private var connection: Connection = null
  private var ps: PreparedStatement = null

  /**
    * 在open()方法中建立连接,这样不用每次invoke的时候都要建立连接和释放连接。
    */
  override def open(parameters: Configuration): Unit = {
    super.open(parameters)
    val driver = "com.mysql.jdbc.Driver"
    val url = "jdbc:mysql://localhost:3306/bike?characterEncoding=utf-8&useSSL=true"
    val username = "root"
    val password = "123456"
    //1.加载驱动
    Class.forName(driver)
    //2.创建连接
    connection = DriverManager.getConnection(url, username, password)

    val sql = "insert into tb_iris(category,sepalLength,sepalWidth,petalLength,petalWidth,insertTime) values(?,?,?,?,?,?);"

    //3.获得执行语句
    ps = connection.prepareStatement(sql)
  }

  /**
    * 每个元素的插入都要调用一次invoke()方法进行插入操作
    */
  override def invoke(value: Iris): Unit = {
    try {
      ps.setString(1, value.category)
      ps.setDouble(2, value.sepalLength)
      ps.setDouble(3, value.sepalWidth)
      ps.setDouble(4, value.petalLength)
      ps.setDouble(5, value.petalWidth)
      ps.setLong(6, System.currentTimeMillis())
      ps.executeUpdate()
    } catch {
      case e: Exception => println(e.getMessage)
    }
  }

  /**
    * 关闭连接
    */
  override def close(): Unit = {
    super.close()
    if (connection != null) {
      connection.close()
    }
    if (ps != null) {
      ps.close()
    }
  }
}

运行主程序

  object mongoSourceTest {

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

    val env = StreamExecutionEnvironment.getExecutionEnvironment

  // 获取source的数据
    val iris = env.addSource(new MongodbSource())
      .flatMap(_.toSeq)
    
    // 中间的数据处理逻辑省略
    
    iris.addSink(new MysqlSink)
    
    env.execute("Flink add mongo data sourc")

  }
}

数据结果
Mysql 数据结果

### 回答1: Flink自定义SinkSource是指用户可以根据自己的需求,编写自己的数据源数据输出方式。Flink提供了一些内置的SinkSource,但是有时候用户需要根据自己的业务需求,自定义数据源数据输出方式。 自定义SinkSource需要实现Flink提供的接口,例如实现SinkFunction接口来自定义数据输出方式,实现SourceFunction接口来自定义数据源。用户可以根据自己的需求,实现这些接口,然后将自定义SinkSource应用到Flink程序中。 自定义SinkSource可以帮助用户更好地满足自己的业务需求,提高数据处理的效率准确性。 ### 回答2: Flink自定义SinkSource方便开发人员根据特定业务需求定制化的数据输入输出。这也是Flink作为DataStream处理引擎的一个强大特性。 自定义Sink的主要作用是将Flink处理的数据流输出到外部存储或处理系统中,如Kafka、Hadoop、Elasticsearch、MySQL等。通过自定义Sink,我们可以满足不同业务场景下,数据输出的不同需求。 自定义Sink的实现需要继承Flink提供的`RichSinkFunction`或者`SinkFunction`抽象类,并实现其抽象方法。`RichSinkFunction`中提供了一些状态管理的方法,如`open`、`close`等,我们可以在这些方法中添加额外的代码逻辑。自定义SinkFunction可以重写invoke方法,将不需要状态管理的代码集中在此方法中。 自定义Source的主要作用是将外部数据源中的数据读取并发送给Flink的DataStream处理模块。自定义Source可以读取各种类型的数据源,如Kafka、文件、Socket等。 自定义Source的实现需要继承Flink提供的`RichParallelSourceFunction`或者`SourceFunction`抽象类,并实现其抽象方法。`RichParallelSourceFunction`中支持在并行算子中运行,因此对于大规模数据的处理尤为适合。 在自定义Source中,需要实现一个`run`方法一个`cancel`方法。`run`方法中是数据源处理逻辑的主要实现,`cancel`方法用于停止数据源的读取。我们还可以通过Flink提供的Checkpoint机制来管理数据源。 总之,自定义SinkSourceFlink处理数据流的重要特性,使得开发人员可以根据业务需求灵活定制化的输入输出逻辑。 ### 回答3: Flink是一个开源流式处理框架,它提供了丰富的内置SinkSource,同时也支持用户自定义SinkSource,以便满足不同的业务需求。 自定义Sink可以用于将流式数据写入外部系统中,比如数据库、消息队列文件系统等。Flink提供了一个简单的接口SinkFunction,通过实现该接口可以快速开发自己的SinkSinkFunction接口定义了一个抽象方法invoke(),该方法是在每个输入元素处理完成时被调用。开发者需要编写自己的业务逻辑,在invoke()中实现将数据写入目标系统的逻辑。 自定义Source可以用于从外部系统读取数据,并将其逐个交付给Flink程序进行处理。同样地,Flink也提供了一个简单的接口SourceFunction,通过实现该接口可以快速开发自己的SourceSourceFunction接口定义了两个抽象方法:run()cancel()。run()方法是在源自生命周期内调用的,它是源自执行主逻辑的地方。cancel()方法是用于清理资源的。开发者需要在run()方法中编写从外部系统读取数据的逻辑,并且能够异步地产生数据,最后将数据通过SourceContext将数据一条一条源源不断地输出。 自定义SinkSourceFlink框架中非常常用的一个扩展方式,它可以满足用户自定义的需求,在具体的业务场景中,能够灵活的使用自定义SinkSource对数据的处理进行个性化的定制化。同时,自定义SinkSource的开发也相对简单,可以通过实现简单的接口,快速完成自定义SinkSource的开发。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值