Flink程序遵循一定的编程模式。DataStream API 和 DataSet API 基本具有相同的程序结构。以下为一个流式程序的示例代码来对文本文件进行词频统计。

package com.realtime.flink.streaming
import org.apache.flink.apijava.utils.ParameterTool
import org.apache.flink.streaming.api.scala.{DataStream, StreamExecutionEnvironment, _} object WordCount {
def main(args: Array[String]) {
//第一步:设定执行环境
val env = SreamExecutionEnvironment.getExecutionEnvironment
//第二步:指定数据源地址,开始读取数据
val text = env.readTextFile("file:///path/file")
//第三步:对数据集指定转换操作逻辑
val counts : DataStream[(String, int)] = text
.flatMap(_.toLowerCase.split(" "))
.fliter(_.nonEmpty)
.map(_, 1)
.sum(1)
//第四步:指定计算结果输出位置
if (params.has("output")) {
counts.writeAsText(params.get("output"))
} else {
println("Printing resule to stdout. Use --output to specify output path.")
counts.print()
}
//第五步:指定名称并触发流式任务
env.execute("Streaming WordCount")
}
}

整个Flink 程序一共分为5步:

1. Flink执行环境

不同的执行环境决定了应用的类型:

StreamExecutionEnvironmen用来流式处理,ExecutionEnvironment是批量数据处理环境.

获取环境的三种方式:

  • 流处理:

    //设定Flink运行环境,如果在本地启动则创建本地环境,如果在集群启动就创建集群环境
    StreamExecutionEnvironment.getExecutionEnvironment
    //指定并行度创建本地执行环境
    StreamExecutionEnvironment.createLocalEnvironment(5)
    //指定远程JobManager ip和RPC 端口以及运行程序所在的jar包和及其依赖包
    StreamExecutionEnvironment.createRemoteEnvironment("JobManagerHost", 6021, 5, "/user/application.jar")

    第三种方式直接从本地代码创建与远程集群的JobManager的RPC连接,指定jar将运行程序远程拷贝到JobManager节点上,Flink应用程序运行在远程的环境中,本地程序相当于一个客户端.

  • 批处理:

  //设定Flink运行环境,如果在本地启动则创建本地环境,如果在集群启动就创建集群环境
ExecutionEnvironment.getExecutionEnvironment
//指定并行度创建本地执行环境
ExecutionEnvironment.createLocalEnvironment(5)
//指定远程JobManager ip和RPC 端口以及运行程序所在的jar包和及其依赖包
ExecutionEnvironment.createRemoteEnvironment("JobManagerHost", 6021, 5, "/user/application.jar")

注意不同的语言开发Flink应用的时候需要引入不同环境对应的执行环境

2. 初始化数据

  • 创建完执行环境, ExecutionEnvironment 需要提供不同的数据接入接口完成数据初始化,将外部数据转换成DataStream 或DataSet数据集.

  • Flink提供了多种从外部读取数据的连接器,包括批量和实时的数据连接器,能够将Flink系统与其他第三方系统进行连接,直接获取外部数据

  • 以下代码通过readTextFile()方法读取flle://pathfile路径中的数据并转换成DataStream数据集.

val text: DataStream[String] = env.readTextFlie("flle://pathfile")

读取文件转换为DataStream[String]数据集,完成了从本地文件到分布式数据集的转换

3. 执行转换操作

对数据集的各种Transformation操作通过不同的Operator来实现,每个Operator来实现,每个Operator内部通过实现Function接口完成数据处理逻辑的定义.

DataStream API 和 DataSet API 提供了很多转换算子, 如: map, flatMap, filter, keyBy, 用户只需要定义每个算子执行的函数逻辑,然后应用在数据转换操作Operator 接口即可.

 val counts: DataStream[String, Int] = text
.flatMap(_.toLowerCase.split(" ")) //执行flatMap操作
.filter(_.nonEmpty) //过滤空字段
.map((_, 1) //执行map转换操作,转换成key - value 接口
.keyBy(0) // 按照指定key对数据重分区
.sum(1) /执行求和运算操作

flink 定义Function的计算逻辑可以通过以下几种方式完成定义:

1. 通过创建Class 实现Function接口

//实现MapFunction接口
class MyMapFunction extends MapFunction[String, String] {
override def map(t: String): String {
t.toUpperCase()
}
} val dataStream: DataStream[String] = env.fromElements("hello", flink)
//将MyMapFunction实现类传入进去
dataStream.map(new MyMapFunction)

完成对实现将数据集中的字符串转换成大写的数据处理

2. 通过创建匿名类实现Function接口

 val dataStream: DataStream[String] = env.fromElements("hello", flink)
//通过创建MapFunction匿名实现类来定义map函数的计算逻辑
dataStream.map(new MapFunction[String, String] {
//实现对输入字符串大写转换
override def map(t: String): String{
t.toUpperCase()
}
})

3. 通过实现RichFunction接口

Flink提供了RichFunction接口,用于比较高级的数据处理场景,RichFunction接口中有open、close、getRuntimeContext 以及setRuntimeContext来获取状态、缓存等系统内部数据. 与MapFunction类似,RichFunction子类也有RichMapFunction.

//定义匿名类实现RichMapFunction接口,完成对字符串到整形数字的转换
dataStream.map(new RichMapFunction[String, Int] {
//实现对输入字符串大写转换
override def map(in: String):Int = (in.toInt)
})

4.分区key指定

某些算子需要指定的key进行转换,常见的算子有: join 、coGroup、groupBy.需要将DataStream或DataSet数据集转换成对应KeyedStream 和GroupDataSet ,主要是将相同key的数据路由到相同的Pipeline中

1.根据字段位置指定

//DataStream API聚合计算

val dataStream : DataStream[(String,Int)] = env.fromElements(("a", 1),("c", 2))

//根据第一个字段重新分区,然后对第二个字段进行求和计算
val result = dataStream.keyBy(0).sum(1)
//DataSet API 聚合计算
val dataSet = env.fromElements(("a", 1),("c", 2))
//根据第一个字段进行数据重分区
val groupDataSet : GroupDataSet[(String , Int)] = dataSet.groupBy(0)
//求取相同key值第二个字段的最大值
groupDataSet.max(1)

2.根据字段名称指定

使用字段名称需要DataStream 中的数据结构类型必须是Tuple类或者POJOs类

val personDataSet = env.fromElements(new Person("Alex", 18), new Person("Peter", 43))
//指定name字段名称来确定groupBy 字段
personDataSet.groupBy("name").max(1)

如果程序中使用Tuple数据类型,通常情况下字段名称从1开始计算,字段位置索引从0开始计算

val personDataStream = env.fromElements(new Person("Alex", 18), new Person("Peter", 43))
//通过名称指定第一个字段
personDataStream.keyBy("_1") //通过位置指定第一个字段
personDataStream.keyBy(0)

使用嵌套的复杂数据结构:

class NestedClass {
var id: int,
tuples: (Long, Long, String)){
def this() {
this(0, (0, 0, " "))
}
} class CompelexClass(var nested: NestedClass, var tag: String) {
def this() {
this(null, " ")
}
}

通过“nested”获取整个NestedClass对象所有字段,调用“tag”获取 CompelexClass中tag字段,调用“nested.id”获取NestedClass的id字段,调用“nested.tuples._1”获取NestedClass中tuple元祖第一个字段

3. 通过Key选择器指定

定义KeySelector,然后复写getKey方法,从Person对象中获取name为指定的Key.

case class Person(name: String, age: Int)
var person = env.fromElements(Person("hello", 1), Person("Flink", 3) )
//
val keyed: KeyedStream[WC] = person.keyBy(new KeySelector[Person, String](){
override def getKey(person: Person): String = person.name
})

5.输出结果

数据进行转换操作之后,一般会输出到外部系统或者控制台上.Flink 除了基本的数据输出方法,在系统中还定义了很多Connector,用户通过调用addSink()添加输出系统定义的DataSink类算子,这样就可以将数据输出到外部系统.

//将数据输出到文件中
counts.writeAsText("file://path/to/savefile")
//将数据输出控制台
counts.print()

程序触发

计算逻辑全部操作定义好后,需要调ExecutionEnvironment的execute()方法来触发程序的执行,execute()方法返回的结果类型为JobExecutionResult,JobExecutionResult包含了程序执行的时间和累加器等指标.

注意: DataStream流式应用需要显示调用execute()方法,否则Flink应用程序不会执行.但对于DataSet API 输出算子已经包含对execute()方法的调用,不再需要显示调用了,否则会出现程序异常.

//调StreamExecutionEnvironment的execute()方法来执行流式应用程序
env.execute("App Name")

总结

本文主要介绍了Flink应用程序开发的5步:获取执行环境;初始化数据;执行转换操作;分区key指定;输出结果以及程序的触发等开发模式以及内部的一些实现细节.

Flink应用程序结构开发介绍的更多相关文章

  1. 【Demo 0001】Android 程序结构

    Android 学习步骤及内容:     1.  Android 程序结构(开发环境搭建,Android第一程序,程序启动过程以及工程介绍):     2.  Android 事件(通用使用规则,通用 ...

  2. 如何进行Flink项目构建,快速开发Flink应用程序?

    项目模板 Flink应用项目可以使用Maven或SBT来构建项目,Flink针对这些构建工具提供了相应项目模板. Maven模板命令如下,我们只需要根据提示输入应用项目的groupId.artifac ...

  3. 小程序的目录结构/配置介绍/视图层wxml数据绑定/双线程模型/小程序的启动流程

    安装好微信小程序开发软件,创建项目 小程序文件结构和传统web对比 结构 传统web 微信小程序 结构 HTML WXML 样式 CSS WXSS 逻辑 Javascript Javascript 配 ...

  4. 微信小程序结构目录、配置介绍、视图层(数据绑定,运算,列表渲染,条件渲染)

    目录 一.小程序结构目录 1.1 小程序文件结构和传统web对比 1.2 基本的项目目录 二.配置介绍 2.1 配置介绍 2.2 全局配置app.json 2.3 page.json 三.视图层 3. ...

  5. 基于Flask的Web应用程序插件式结构开发

    事实上,很多应用程序基于插件式结构开发,可以很方便了扩展软件的功能,并且这些功能完全可以依托于第三方开发者,只要提供好接口和完备文档,比如wordpress.谷歌火狐浏览器等. Python这样的动态 ...

  6. Vue+koa2开发一款全栈小程序(1.课程介绍+2.ES6入门)

    1.课程介绍 1.课程概述 1.做什么? Vue+koa2开发一款全栈小程序 2.哪些功能? 个人中心.图书列表.图书详情.图书评论.个人评论列表 3.技术栈 小程序.Vue.js.koa2.koa- ...

  7. 1   开发一个注重性能的JDBC应用程序不是一件容易的事. 当你的代码运行很慢的时候JDBC驱动程序并不会抛出异常告诉你。   本系列的性能提示将为改善JDBC应用程序的性能介绍一些基本的指导原则,这其中的原则已经被许多现有的JDBC应用程序编译运行并验证过。 这些指导原则包括:    正确的使用数据库MetaData方法    只获取需要的数据    选用最佳性能的功能    管理连

    1 开发一个注重性能的JDBC应用程序不是一件容易的事. 当你的代码运行很慢的时候JDBC驱动程序并不会抛出异常告诉你. 本系列的性能提示将为改善JDBC应用程序的性能介绍一些基本的指导原则,这其中的 ...

  8. 微信小程序 - 结构目录 | 配置介绍

    结构目录 小程序框架提供了自己的视图层描述语言 WXML 和 WXSS,以及 JavaScript,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑. 一.小程序文件结构和传 ...

  9. 为什么要学习微信小程序直播开发?最新的小程序直播介绍和优势分析!

    小程序直播的介绍 “小程序直播”是微信提供给开发者的实时视频直播工具,包括直播管理端.主播端和观众端等模块,支持提供常用的用户互动和营销促销工具. 开发者只需在小程序中引入相关代码并在管理后台完成配置 ...

随机推荐

  1. SpringMVC----执行流程+底层解析

    SpringMVC流程图如上面所示,根据上图,串联一下底层源码: 1.在DispatcherServlet中找到doDisPatch 2.观察方法体,然后找到getHandler方法 3.点进方法,发 ...

  2. CSPS模拟 59

    经ooo提醒咕题解会掉rp 我反正也冒着改不完题的风险,就开始颓博了 话说好久没这么舒坦的垫过底了233 上来一看T1,立刻就转化题意为有奇偶性和距离限制的bfs 然后就没考虑子串不能越过母串边界的事 ...

  3. 2、linu

    一.常用linux命令 昨日内容回顾 linux基本命令 ls 查看目录和文件ls -la 查看所有文件和目录详情(包括隐藏文件, -l和-a可以单独使用)mkdirrmdirtouchcatcdrm ...

  4. windows使用docker运行mysql等工具(一)windows安装docker

    由于我本地的mysql版本比较低,最近想着要升级一下mysql版本,鉴于docker容器的火热,就想着在本地装个docker环境,然后下载最新版的mysql镜像,完成mysql8.0的安装.电脑是wi ...

  5. 微信小程序云开发获取文件夹下所有文件

    上周一个高中同学让我帮他做个图片展示的公众号,因为一直在加班的原因,所以一时忘了,昨晚想起来就赶紧加班加点的帮他弄了下,遇到了个问题,记录一下. 他的需求是要有个后台给他上传图片并且将图片归类,前端公 ...

  6. P0-Logisim简单部件与有限状态机

    #自学了6week,pre都挂了,做了做P0课下测试,觉得自己对有限状态机概念的的理解,特别是牵扯到时序还是很模糊:状态的抽象也不够熟练:logisim和Verilog的实现也存在问题.网上针对性的l ...

  7. 心里有点B树

    在说B树之前最好先看看2-3树, 2-3树是B树的一种特例, 什么B树, B树就是2-3树, 2-3-4 树 , 2-3-4-5... 树的统称, 而B+树又是B树的一种变形 性质: 什么是二节点, ...

  8. nyoj 54-小明的存钱计划 (遍历 + 判断)

    54-小明的存钱计划 内存限制:64MB 时间限制:3000ms Special Judge: No accepted:5 submit:11 题目描述: 小明的零花钱一直都是自己管理.每个月的月初妈 ...

  9. 命令序列 ; & && ||

    ; 从左到右依次被执行,返回最后一个命令的执行状态 & 该命令将在后台被执行,即在子bash中执行(或ctrl+z,bg, jobs,bg 命令号)(变量$!.$one.$two.$three ...

  10. vant-ui的van-area使用

    由于官方例子中并没有太多详情,因此记录之,方便以后使用. 1.配置 :area-list="areaList",以初始化全部省市区的数据,其中area.js文件在官方可以下载,放于 ...