flink的常用Source和Sink

本文介绍了如何在Flink中使用KafkaSource和KafkaSink进行实时数据流处理,以及自定义的MySqlSource和MySqlSink实现数据的读写。通过示例代码展示了如何配置Kafka消费者和生产者,以及如何连接到MySQL数据库进行数据读取和写入操作,从而实现数据的完整流转。
摘要由CSDN通过智能技术生成

一、KafkaSource和KafkaSink

  由于flink经常用于对数据实时流进行处理,而我们经常使用Kafka可以对流数据进行削峰处理,所以flink Streaming经常和kafka一起使用
  在flink中已经对kafka的source和sink进行比较高的整合度了,所以使用很方便

def main(args: Array[String]): Unit = {
    val env = StreamExecutionEnvironment.getExecutionEnvironment
    val result= env.readTextFile("filePath")
      .flatMap(_.split(" "))
      
	//addSource
	//kafka的consumer拿到数据供flink分析
	val props = new Properties()
    props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"node1:9092,node2:9092")
    props.setProperty(ConsumerConfig.GROUP_ID_CONFIG,"cxv")
    val inputStream = env.addSource(new FlinkKafkaConsumer[String]("test", new SimpleStringSchema(), props))	

	//addSink
	//这里将从flink流中读出的数据放入kafka中,相当于是kafka的消费者
    result.addSink(new FlinkKafkaProducer[String]("node1:9092","test",new SimpleStringSchema()))

    env.execute()
  }

标题二、MySqlSource(自定义)和MySqlSink(自定义)

MysqlSource

def main(args: Array[String]): Unit = {
    val env = StreamExecutionEnvironment.getExecutionEnvironment

    env.addSource(new MyJdbcSourceFunc)
      .print()

    env.execute()
  }
}

//继承RichParallelSourceFunction,实现其中的方法
class MyJdbcSourceFunc extends RichParallelSourceFunction[Worker]{
  var conn:Connection = _
  var pst:PreparedStatement = _
  var flag = true

  //建立数据库连接
  override def open(parameters: Configuration): Unit = {
    conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testevery?characterEncoding=utf-8&&useSSL=false&serverTimezone=UTC","root","1994")
    pst = conn.prepareStatement("select * from worker")
  }


  //从数据库中取数据
  override def run(ctx: SourceFunction.SourceContext[Worker]): Unit = {
    while (flag){
      Thread.sleep(500)
      val rs = pst.executeQuery()
      while (rs.next()){
        val name = rs.getString(1)
        val salary = rs.getLong(2)

        ctx.collect(Worker(name,salary))
      }
    }
  }

  override def cancel(): Unit = {
    flag=false
  }
 //关闭连接
  override def close(): Unit = {
    if (pst != null) pst.close()
    if (conn != null) conn.close()

  }
}

MysqlSink

//定义一个Worker样例类
case class Worker(name:String,salary:Long)

def main(args: Array[String]): Unit = {
    val env = StreamExecutionEnvironment.getExecutionEnvironment
    val dataStream = env.readTextFile("filePath")
      .map(line => {
        val ps = line.split(",")
        Worker(ps(0).toString, ps(1).toLong)
      })

    dataStream.addSink(new MyJDBCSinkFunc)

    env.execute()
  }
}

class MyJDBCSinkFunc extends RichSinkFunction[Worker]{
 var conn:Connection = _
  // 检查数据库有没有,没有就插入,有就更新
  var upDateStatement:PreparedStatement = _
  var insertStatement:PreparedStatement = _


  // 创建数据库连接
  override def open(parameters: Configuration): Unit = {
      conn = DriverManager.getConnection(
        "jdbc:mysql://localhost:3306/testevery?characterEncoding=utf-8&useSSL=false&serverTimezone=UTC",
        "user",
        "password")

      upDateStatement = conn.prepareStatement("update worker set salary=? where name=?")
      insertStatement = conn.prepareStatement("insert into worker values(?,?)")
    }

    override def invoke(value: Worker, context: SinkFunction.Context): Unit = {
      upDateStatement.setString(2,value.name)
      upDateStatement.setLong(1,value.salary)
      upDateStatement.execute()
      if (upDateStatement.getUpdateCount == 0){
        insertStatement.setString(2,value.name)
        insertStatement.setLong(1,value.salary)
        insertStatement.execute()
      }
    }

    // 关闭数据库连接
    override def close(): Unit = {

      if (insertStatement != null) insertStatement.close()
      if (upDateStatement != null) insertStatement.close()
      if (conn != null) insertStatement.close()
  }
}

### 回答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的主要作用是将外部数据源中的数据读取并发送给FlinkDataStream处理模块。自定义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的开发。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值