flink学习(七)——DataStream API介绍

前面我们尝试用flink写了一个WordCount程序,并且介绍了flink提供的api层级,接下来我们正式来学习flink的DataStream API。

为什么先学习DataStream API,而不是ProcessFunction API,这是因为ProcessFunction API是通过DataStream API调用的,它作为DataStream API的补充,可以实现DataStream API所不能实现的一些高级功能。

什么是DataStream

在开始介绍DataStream的API之前,我们先来看一下什么是DataStream。

以flink程序角度来讲,DataStream,如其中文名,数据流,是一个特殊的类,这个类表示了数据的集合,并且数据是不可变的,但可以是重复的。而对于数据流来说,我们前面说过,它可以是有界的也可以是无界的,可以对DataStream进行各种转换得到不同的DataStream。

我们可以这样类比,把DataStream理解成一个溪流,数据是溪流里面的水

  1. 流水是无法变更的,流过去就流过去了,即表示数据是不可变的。
  2. 溪流弯弯曲曲的流向远方,有千转百折,即是我们定义在DataStream上相关的转换。
  3. 溪流的水可以一直流,这是无界的,也可以流了之后断掉,就是有界的。

DataStream程序结构剖析

我们再回到WordCount的那个例子(只保留了代码主体部分):

// 1. 获取流任务执行环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

// 2. 输入,这里使用了自带的socket输入,监听ip地址为hadoop001,端口号为9999
DataStream<String> source = env.socketTextStream("hadoop001", 9999);

// 3. 数据转换处理
DataStream<Tuple2<String, Integer>> counted = source
    .map(xxx)
    .keyBy(xxx)
    .sum(1)
;

// 4. 输出,这里使用了自带的控制台输出,将结果输出到控制台
counted .print("output");

// 5. 执行流任务
env.execute("word count test");

DataStream API程序跟很多数据处理程序一样,主要分为:

  1. 数据输入
  2. 数据转化处理
  3. 数据输出

在执行程序之前,我们要获取到执行上下文环境,所以DataStream API中先要创建执行环境。

而flink的执行方式是惰式执行(即先定义数据处理计划,最后再执行),并且对于流式数据而言,都是数据(事件)驱动,只能事先定义好数据处理逻辑,所以最后还要加一个启动命令告诉flink开始执行job。

最终我们可以得到一个flink DataStream API程序由以下5部分组成:

  1. 获取流任务执行环境
  2. 加载/创建数据源
  3. 指定数据转换方式
  4. 指定数据处理结果要输出到什么地方
  5. 触发程序执行

获取流任务执行环境

我们可以通过以下方式来获取执行环境:

1. getExecutionEnvironment()

2. createLocalEnvironment()

3. createRemoteEnvironment(String host, int port, String... jarFiles)

不过,我们一般只用到getExecutionEnvironment方法,因为它会智能地根据上下文创建合适的执行环境:

  1. 如果我们在IDE或将它作为一个普通的java程序中执行,它会创建一个本地环境并且在本机上执行我们的程序。
  2. 如果我们创建了一个jar包,并且通过命令行的方式启动,那么flink集群管理器会执行主程序并且getExecutionEnvironment()会返回一个适合该集群的执行环境。

任务执行环境对象也提供了api方便我们设置一些参数:

// 执行参数配置
ExecutionConfig executionConfig= env.getConfig();

// checkpoint相关参数配置
CheckpointConfig checkpointConfig = env.getCheckpointConfig();

现在我们无需了解,相关配置等用到的时候再学习。

加载/创建数据源

数据源(Data Sources)是我们程序读取数据的来源,来源的方式可以有很多种:文件系统、网络io、数据库、消息队列等,同时也可以来自于内存(从内存创建数据源)。只要能提供数据的都可以作为数据源,比如我们从文件里面读数据:

final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

DataStream<String> text = env.readTextFile("file:///path/to/file");

而前文WordCount例子中,我们读取的是来自于网络socket的数据:

DataStream<String> source = env.socketTextStream("hadoop001", 9999);

从内存中读取可以这样写:

List<String> word = new ArrayList<>();

word.add("hello");
word.add("world");
word.add("flink");

DataStream<String> flintstones = env.fromCollection(word);

当然了,在实际应用程序中,我们很少这样写,更多使用的是低延迟,高吞吐的可重放数据源,如kafka等。

上面举的几个例子都是flink中已经实现好的读取数据源的方式,我们可以使用StreamExecutionEnvironment.addSource(sourceFunction)方法,通过实现SourceFunction接口来自定义数据源。

指定数据转换方式

数据转换方式就是实现我们数据处理逻辑的地方。我们可以把输入的DataStream经过一系列的数据转换变成新的DataStream。我们可以直接在DataStream对象后面直接跟数据转换方法,如下面的map操作:

DataStream<String> input = ...;

DataStream<Integer> parsed = input.map(new MapFunction<String, Integer>() {
    @Override
    public Integer map(String value) {
        return Integer.parseInt(value);
    }
});

这步map操作将String转换为了Integer,并且以此创建了一个新的DataStream。数据转换方式有很多,具体的api我们后面再详细介绍学习。

指定数据处理结果要输出到什么地方

数据经过一系列的转换之后得到了我们需要的结果,那么这个时候我们可以通过数据汇(Data Sinks)就要将它输出到指定的地方,如数据库中,供后续的查询使用。数据可以简单地写出到文件或控制台中:

writeAsText(String path) // 将数据以文本方式写出到文件中

print() // 将数据打印到控制台

这些方法是flink内置的数据写出方法,我们也可以自定义数据汇写出到我们感兴趣的地方:

env.addSink(SinkFunction);

触发程序执行

最后我们通过调用execute()方法来执行程序。根据我们的执行环境的不同,它会将程序提交到不同的地方执行。如果是本地环境,则在本机上执行;如果是集群环境,则提交到相应的集群上执行。通常我们需要给execute()方法传递一个String对象,即为job名称,以方便我们查看,如果不指定,程序会默认使用Flink Streaming Job作为job名称,如:

execute("My First Flink Streaming Job")

需要注意的是,execute()是个同步方法,它会一直等待到job执行结束,然后返回一个JobExecutionResult对象,在这个对象中包含了job执行时间和聚合结果等等,一般我们使用execute()方法已经足够了。不过如果你不想等到job结束,就去做其他的事情,flink也提供了一个异步方法:executeAsync()。它会返回一个JobClient对象,这个对象可以与我们刚刚提交的job进行交互,并获取结果:

final JobClient jobClient = env.executeAsync();

final JobExecutionResult jobExecutionResult = jobClient.getJobExecutionResult().get();

不过这个不怎么常用,知道一下就好。

flink程序都是惰式执行的,所有的数据加载、数据转换操作和数据写出操作都不会立即执行。在flink学习(四)——flink任务执行原理详解中,我们提到了flink会根据用户的api生成StreamGraph,而这一步就是在execute()方法里面完成的。数据执行图构建好之后,程序就会根据执行环境实际地在本机或集群上运行起来。

DataStream API总结

对于日常开发来说,我们使用最多的是数据转换的API,因为flink已经内置了很多常见的Data Sources和Data Sinks。而窗口计算、带时间编程、有状态编程都是在数据转换api中,这块将是我们接下来学习的重点。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值