Flink之Source

8 篇文章 0 订阅
7 篇文章 0 订阅

Flink 可以从各种来源获取数据,然后构建 DataStream 进行转换处理。一般将数据的输入来源称为数据源,而读取数据的算子就是源算子(Source)。所以,Source 就是我们整个处理程序的输入端。

Flink 代码中通用的添加 Source 的方式,是调用执行环境的 addSource()方法:

//通过调用 addSource()方法可以获取 DataStream 对象
val stream = env.addSource(...)

方法传入一个对象参数,需要实现 SourceFunction 接口,返回一个 DataStream。

首先先准备数据,假设数据来源是网页的埋点数据,数据格式为(用户名,网址,时间戳)的三元组,此处用case class样例类来表示数据格式。

字段名

数据类型

说明

user

String

用户名

url

String

网址

timestamp

long

时间戳

样例类代码如下:

object CC {

  //  用户浏览事件  用户名 网址 时间戳
  case class Event(user: String, url: String, timestamp: Long)

}
  • 从集合中读取数据

最简单的读取数据的方式,就是在代码中直接创建一个集合,然后调用执行环境的fromCollection 方法进行读取。这相当于将数据临时存储到内存中,形成特殊的数据结构后,作为数据源使用,一般用于测试。

  def main(args: Array[String]): Unit = {
//    获取流执行环境
    val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
//    设置并行度为1
    env.setParallelism(1)
//    读取Event集合
    val stream: DataStream[Event] = env.fromCollection(List(
      Event("zhangsan", "index.html", 1L),
      Event("lisi", "commom.jsp", 10L),
      Event("wangwu", "baidu.com", 10L)))
    stream.print()
    env.execute()
  }
  • 从文件中读取

 //    读文本文件  有界的数据流
val stream: DataStream[String] = env.readTextFile("input/words.txt")
val sum: DataStream[(String, Int)] = stream
      .flatMap(_.split(" ")) // 按照空格切分扁平化
      .map((_, 1)) // (word,1) 二元组
      .keyBy(_._1) // 根据第一个元素聚合
      .sum(1) // 按照index 1 位置求和
sum.print()
  • 从Socket中读数据

不论从集合还是文件,我们读取的其实都是有界数据。在流处理的场景中,数据往往是无界的。一个简单的例子,就是我们之前用到的读取 socket 文本流。这种方式由于吞吐量小、稳定性较差,一般也是用于测试。

//    数据源读取socket文本流数据
    val stream: DataStream[String] = env.socketTextStream("192.168.0.30", 7777)
  • 从Kafka读数据

Kafka 作为分布式消息传输队列,是一个高吞吐、易于扩展的消息系统。而消息队列的传输方式,恰恰和流处理是完全一致的。所以可以说 Kafka 和 Flink 天生一对,是当前处理流式数据的双子星。在如今的实时流处理应用中,由 Kafka 进行数据的收集和传输,Flink 进行分析计算,这样的架构已经成为众多企业的首选。

Flink 官方提供了连接工具 flink-connector-kafka,直接帮我们实现了一个消费者FlinkKafkaConsumer,它就是用来读取 Kafka 数据的 SourceFunction。所以想要以 Kafka 作为数据源获取数据,我们只需要引入 Kafka 连接器的依赖。Flink 官方提供的是一个通用的 Kafka 连接器,它会自动跟踪最新版本的 Kafka 客户端。目前最新版本只支持 0.10.0 版本以上的 Kafka。

添加pom文件配置

<dependency>
      <groupId>org.apache.flink</groupId>
      <artifactId>flink-connector-kafka_${scala.binary.version}</artifactId>
      <version>${flink.version}</version>
</dependency>

然后调用 env.addSource(),传入 FlinkKafkaConsumer 的对象实例就可以了。

import java.util.Properties

import org.apache.flink.api.common.serialization.SimpleStringSchema
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer
import org.apache.kafka.clients.consumer.ConsumerConfig

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

    val env = StreamExecutionEnvironment.getExecutionEnvironment

    val props = new Properties()
    props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.0.30:9092")
    props.setProperty(ConsumerConfig.GROUP_ID_CONFIG, "flink_test")

    val stream = env.addSource(new FlinkKafkaConsumer[String]("mytest", new SimpleStringSchema(), props))
    stream.print()
    env.execute()
  }

创建 FlinkKafkaConsumer 时需要传入三个参数:

  1. 第一个参数 topic,定义了从哪些主题中读取数据。可以是一个 topic,也可以是 topic列表,还可以是匹配所有想要读取的 topic 的正则表达式。当从多个 topic 中读取数据时,Kafka 连接器将会处理所有 topic 的分区,将这些分区的数据放到一条数据流中去。

  1. 第二个参数是一个 DeserializationSchema 或者 KeyedDeserializationSchema。Kafka 消息被存储为原始的字节数据,所以需要反序列化成 Java 或者 Scala 对象。上面代码中使用的 SimpleStringSchema,是一个内置的 DeserializationSchema,它只是将字节数组简单地反序列化成字符串。DeserializationSchema 和 KeyedDeserializationSchema 是公共接口,所以我们也可以自定义反序列化逻辑。

  1. 第三个参数是一个 Properties 对象,设置了 Kafka 客户端的一些属性。

  • 自定义源算子(Source)

接下来我们创建一个自定义的数据源,实现 SourceFunction 接口。主要重写两个关键方法:run()和 cancel()。

  1. run()方法:使用运行时上下文对象(SourceContext)向下游发送数据;

  1. cancel()方法:通过标识位控制退出循环,来达到中断数据源的效果。

代码如下:

package com.myproject.entity

import com.myproject.entity.CC.Event
import org.apache.flink.streaming.api.functions.source.SourceFunction
import scala.util.Random

class ClickSource extends SourceFunction[Event] {

  var running = true

  override def run(ctx: SourceFunction.SourceContext[Event]): Unit = {
    val random = new Random()
    val users = List("zhangsan", "lisi", "wangwu", "laoliu")
    val urls = List("baidu.com", "sohu.com/index.html", "sina.cn", "12306.com","https://zhuanlan.zhihu.com")
    // 用标志位作为循环判断条件,不停地发出数据
    while (running) {
      val event = Event(users(random.nextInt(users.length)), urls(random.nextInt(urls.length)), System.currentTimeMillis())
      // 调用ctx的方法向下游发送数据
      ctx.collect(event)
      // 每隔1s发送一条数据
      Thread.sleep(1000)
    }
  }

  override def cancel(): Unit = {
    running = false
  }
}

这个数据源,我们后面会频繁使用,之后的代码若涉及 ClickSource()数据源,使用上面的代码就可以了。

下面的代码我们来读取一下自定义的数据源。有了自定义的 Source,接下来只要调用addSource()就可以了:

package com.myproject.analyse

import com.myproject.entity.ClickSource
import org.apache.flink.streaming.api.scala._

object DiySourceStreaming {
  def main(args: Array[String]): Unit = {
    val env = StreamExecutionEnvironment.getExecutionEnvironment
    env.setParallelism(1)
    val lineDS = env.addSource(new ClickSource)
    lineDS.print()

    env.execute()
  }

}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Flink提供了一个HBase源(HBaseTableSource),可以用于从HBase表中读取数据并将其转换为Flink流。使用HBaseTableSource,您可以定义一个HBase表,指定要读取的列族和列,并指定扫描过滤器以过滤数据。下面是一个简单的示例: ```java // 创建HBase表源 HBaseTableSource hbaseSource = new HBaseTableSource( // 表名 "my_table", // 列族和列 new String[] {"cf1", "cf2"}, new String[] {"col1", "col2", "col3"}, // 扫描过滤器 new SingleColumnValueFilter("cf1", "col1", CompareOperator.EQUAL, new BinaryComparator(Bytes.toBytes("value"))) ); // 创建Flink流执行环境 StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); // 读取HBase表数据并转换为Flink流 DataStream<Tuple2<String, String>> dataStream = env.createInput(hbaseSource) .map(new MapFunction<Row, Tuple2<String, String>>() { @Override public Tuple2<String, String> map(Row row) throws Exception { return new Tuple2<String, String>(row.getString("cf1:col1"), row.getString("cf2:col2")); } }); ``` 上面的示例中,我们创建了一个HBaseTableSource来读取名为"my_table"的HBase表。我们指定要读取的列族为"cf1"和"cf2",要读取的列为"col1"、"col2"和"col3",并指定了一个扫描过滤器来过滤数据。然后,我们使用createInput方法将HBaseTableSource转换为Flink流,并使用map方法将Row对象转换为Tuple2<String, String>对象,最终得到一个包含HBase表数据的Flink流。 ### 回答2: Flink HBase Source是Apache Flink提供的一种用于从HBase中读取数据的组件。HBase是一个分布式的、面向列的NoSQL数据库,而Flink是一个分布式的流处理框架,可以对数据流进行高效的处理和计算。 使用Flink HBase Source可以方便地将HBase中的数据作为输入源,实时地进行流式处理。在Flink程序中,我们可以通过配置HBase的连接信息,并指定需要读取的表名、列族、列等信息,来创建一个HBase Source。在Flink的运行过程中,它会不断地从HBase中读取最新的数据,并将其转换成Flink中的数据流进行处理。 Flink HBase Source的功能非常强大。首先,它支持多版本的数据读取。在HBase中,同一个单元格可以存储多个版本的数据,Flink HBase Source可以按照指定的时间戳范围读取指定版本的数据。其次,它支持按照列族和列进行筛选,可以只读取需要的数据,提高了读取的效率。另外,Flink HBase Source还支持并行读取数据,可以对分布式HBase进行高效地读取。 总之,Flink HBase Source为我们提供了一种灵活、高效的方式从HBase中读取数据,能够满足实时处理的需求。无论是进行数据清洗、数据转换、数据分析还是机器学习等操作,我们都可以方便地将HBase中的数据作为输入源,并通过Flink进行流式处理。这对于实时数据处理和分析的场景非常有用。 ### 回答3: Flink HBase Source是Apache Flink提供的一个用于从HBase中读取数据的数据源连接器。HBase是一个基于Hadoop的分布式列式数据库,而Flink是一个流式处理引擎。Flink HBase Source的存在使得我们可以将HBase中的数据作为输入,通过Flink进行实时的流式处理和分析。 Flink HBase Source具有以下几个主要特点: 1. 高效读取数据:Flink HBase Source能够通过HBase的Scan操作从HBase表中高效地读取数据。它可以根据用户指定的查询条件和扫描范围来进行数据的读取,提供灵活的数据访问能力。 2. 实时数据同步:Flink HBase Source可以与HBase表之间建立一个实时的数据同步管道。它可以监控HBase表中的数据更新,并将最新的数据实时传输给Flink应用程序进行处理。这使得我们可以保持Flink应用程序的数据与HBase中的数据保持同步,保证数据的一致性和实时性。 3. 事务一致性保障:Flink HBase Source能够确保读取操作的事务一致性。当一个Flink任务恢复时,它会重新对HBase进行一次全量扫描,并可以保证读取的数据是一致的。同时,Flink HBase Source还支持分布式快照和检查点机制,用于故障恢复和数据一致性的保障。 4. 可伸缩性和高可用性:Flink HBase Source能够根据数据负载的增加或减少来自动调整并发连接数。同时,它还提供了故障自动切换和容错机制,以确保在HBase集群中的节点故障时仍然能够保持任务的高可用性。 总之,Flink HBase Source为我们提供了一个高效、可靠和实时的方式来读取HBase中的数据,并将其集成到Flink的流式处理任务中。它为我们的数据处理工作提供了更强大和灵活的能力,使得我们能够更好地利用HBase和Flink的优势来完成各种数据处理和分析任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不加班程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值