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. 来探讨一下最近面试问的ThreadLocal问题

    中高级阶段开发者出去面试,应该躲不开ThreadLocal相关问题,本文就常见问题做出一些解答,欢迎留言探讨. ThreadLocal为java并发提供了一个新的思路, 它用来存储Thread的局部变 ...

  2. T3hack大部分随机化数据

    1000 2000 1 2 1269 1 3 7707 1 4 3329 4 5 6789 1 6 6691 3 7 -1 1 8 2037 6 9 5427 6 10 5690 4 11 4847 ...

  3. 帝国cms7.5免登陆发布模块

    帝国cms7.5免登陆发布文章. 帝国cms增加了金刚模式,登录发布文章有难度.免登录发布模块配合火车采集器,完美解决你遇到的问题. 1.必备工具: 1.火车采集器 2.免登陆发布接口 3.帝国cms ...

  4. 还看不懂同事的代码?超强的 Stream 流操作姿势还不学习一下

    Java 8 新特性系列文章索引. Jdk14都要出了,还不能使用 Optional优雅的处理空指针? Jdk14 都要出了,Jdk8 的时间处理姿势还不了解一下? 还看不懂同事的代码?Lambda ...

  5. linux系统LAMP环境部署

    一.安装虚拟机 二.安装CentOS7 注意:以下安装,用的root权限. 三.安装Apache 1.安装 yum -y install httpd 2.开启apache服务 systemctl st ...

  6. Unity - Cinemachine实现相机抖动

    普通相机抖动脚本较易实现,但在使用cinemachine相机下,其Transform组件不可被代码改变,那么Cinemachine的相机抖动如何实现呢?本文结合实际项目,对实现相机抖动的三大步骤进行系 ...

  7. ThinkPHP 6.0 管道模式与中间件的实现分析

    设计模式六大原则 开放封闭原则:一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. 里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象. 依赖倒置原则:高层模块不应该依赖低层模块,二者 ...

  8. B2B电商正在向一个新的方向转变

    在互联网+.中国制造2025等国家战略规划的不断催发下,淡出舆论风口多时的B2B电商,开始重新回归公众视野,B2B行业也就此得到一剂强心剂.不过值得关注的是,B2B平台商业模式已经开始发生变革. 互联 ...

  9. IBM-X3850-4U诊断面板信息

    IBM X3850 4U 指示灯 描述 OVERSPEC 没有足够的电量为系统供电.NONRED和LOG指示灯可能也点亮 PS 一个电源故障或者被电源未插 LINK 保留 CPU CPU出现故障.丢失 ...

  10. python:类1——类和对象基础

    一.OO = Object Oriented 面向对象 OOP面向对象编程.OOA面向对象分析.OOD面向对象设计 二.属性+方法——>类(数据和函数) class Turtle(): #类名约 ...