一、Environment

1,getExecutionEnvironment

  getExecutionEnvironment会根据查询运行的方式决定返回什么样的运行环境,是最常用的一种创建执行环境的方式。

2,createLocalEnvironment

  返回本地执行环境,需要在调用时指定默认的并行度。

val env = StreamExecutionEnvironment.createLocalEnvironment() //parallelism

3,createRemoteEnvironment

  返回集群执行环境,将Jar提交到远程服务器。需要在调用时指定JobManager的IP和端口号,并指定要在集群中运行的Jar包。

//hostname port jarFiles
val env = ExecutionEnvironment.createRemoteEnvironment(host, port,"/flink/wc.jar")

4,maven依赖

<dependencies>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-scala_2.</artifactId>
<version>1.7.</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-scala_2.</artifactId>
<version>1.7.</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-kafka-.11_2.</artifactId>
<version>1.7.</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 该插件用于将Scala代码编译成class文件 -->
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.4.</version>
<executions>
<execution>
<!-- 声明绑定到maven的compile阶段 -->
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

二、Source

1,基本读取方式

//文件中读取
val fileDs = env.readTextFile("in/tbStock.txt")
//端口读取
val socketDs = env.socketTextStream("localhost",)
//集合中获取
val collectDs = env.fromCollection(List("aaa","bbb","ccc","aaa"))

2,kafka source

//kafka配置文件
val properties = new Properties()
properties.setProperty("bootstrap.servers", "hadoop102:9092")
properties.setProperty("group.id", "consumer-group")
properties.setProperty("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer")
properties.setProperty("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer")
properties.setProperty("auto.offset.reset", "latest")
//接收kafka的topic-demo这个topic发来的数据
val kafkaDataStream: DataStream[String] = env.addSource(new FlinkKafkaConsumer011[String]("topic-demo", new SimpleStringSchema(), properties))

3,Flink Kafa如何实现exactly-once

可参考: https://www.aboutyun.com/forum.php?mod=viewthread&tid=27395

  Flink通过checkpoint来保存数据是否处理完成的状态

  由JobManager协调各个TaskManager进行checkpoint存储,checkpoint保存在 StateBackend中,默认StateBackend是内存级的,也可以改为文件级的进行持久化保存。

  执行过程实际上是一个两段式提交,每个算子执行完成,会进行“预提交”,直到执行完sink操作,会发起“确认提交”,如果执行失败,预提交会放弃掉。

  如果宕机需要通过StateBackend进行恢复,只能恢复所有确认提交的操作。

4,自定义source

env.addSource(new MySource)
//自定义source
class MySource extends SourceFunction[(String,Double)] {
//flag: 表示数据源是否还在正常运行
var running: Boolean = true
override def cancel(): Unit = {
running = false
}
override def run(ctx: SourceFunction.SourceContext[(String,Double)]): Unit = {
//初始化一个随机数发生器
val rand = new Random()
var curTemp = .to().map(
i => ("item_" + i, + rand.nextGaussian() * )
)
while (running) {
curTemp.foreach(
t => ctx.collect(t)
)
Thread.sleep() //每5秒钟产生一组数据
}
}
}

三、Transform

1,基本转换算子

//map
val streamMap = stream.map { x => x * }
//flatmap
val streamFlatMap = stream.flatMap{
x => x.split(" ")
}
//filter
val streamFilter = stream.filter{
x => x ==
}

2,KeyBy与Reduce

  keyBy(DataStream → KeyedStream):输入必须是Tuple类型,逻辑地将一个流拆分成不相交的分区,每个分区包含具有相同key的元素,在内部以hash的形式实现的。

  reduce(KeyedStream → DataStream):一个分组数据流的聚合操作,合并当前的元素和上次聚合的结果,产生一个新的值,返回的流中包含每一次聚合的结果,而不是只返回最后一次聚合的最终结果。

val keyedStream: KeyedStream[(String, Int), Tuple] = startUplogDstream.map(startuplog=>(startuplog.ch,)).keyBy()
//reduce //sum
keyedStream.reduce{ (ch1,ch2)=>
(ch1._1,ch1._2+ch2._2)
}.print()

3,Split和Select

  split(DataStream → SplitStream):根据某些特征把一个DataStream拆分成两个或者多个DataStream。

  select(SplitStream→DataStream):从一个SplitStream中获取一个或者多个DataStream。

//根据Item的id进行拆分
val splitStream:SplitStream[Item] = dStream.split {
item =>
List(item.id)
}
//获取标记为item_1的数据集
splitStream.select("item_1").print()

4,Connect和CoMap

  connect(DataStream,DataStream → ConnectedStreams):连接两个保持他们类型的数据流,两个数据流被Connect之后,只是被放在了一个同一个流中,内部依然保持各自的数据和形式不发生任何变化,两个流相互独立。

  CoMap,CoFlatMap(ConnectedStreams → DataStream):作用于ConnectedStreams上,功能与map和flatMap一样,对ConnectedStreams中的每一个Stream分别进行map和flatMap处理。

val connStream: ConnectedStreams[StartUpLog, StartUpLog] = appStoreStream.connect(otherStream)
val allStream: DataStream[String] = connStream.map(
(log1: StartUpLog) => log1.ch,
(log2: StartUpLog) => log2.ch
)

4,Union

  DataStream → DataStream:对两个或者两个以上的DataStream进行union操作,产生一个包含所有DataStream元素的新DataStream。注意:如果你将一个DataStream跟它自己做union操作,在新的DataStream中,你将看到每一个元素都出现两次。

val unionStream: DataStream[StartUpLog] = appStoreStream.union(otherStream)
unionStream.print("union:::")

5,ConnectUnion 区别:

  1)Union之前两个流的类型必须是一样,Connect可以不一样,在之后的coMap中再去调整成为一样的。

  2)Connect只能操作两个流,Union可以操作多个

四、实现UDF函数

1,函数类(Function Classes)

  Flink暴露了所有udf函数的接口(实现方式为接口或者抽象类)。例如:MapFunction, FilterFunction, ProcessFunction 等等。

val flinkTweets = tweets.filter(new FlinkFilter)
//自定义filter类
class FlinkFilter extends FilterFunction[String] {
override def filter(value: String): Boolean = { value.contains("flink")
}
}

2,匿名函数(Lamda Functions)

val flinkTweets = tweets.filter(_.contains("flink"))

3,富含数(Rich Functions)

  富函数是 DataStream API 提供的一个函数类的接口,所有 Flink 函数类都有其 Rich 版本。它与常规函数的不同在于,可以获取运行环境的上下文,并拥有一些生命周期方法,所以可以实现更复杂的功能。

  open()方法是 rich function 的初始化方法,当一个算子例如map或者filter被调用之前open()会被调用。

  close()方法是生命周期中的最后一个调用的方法,做一些清理工作。

  getRuntimeContext()方法提供了函数的 RuntimeContext 的一些信息,例如函数执行的并行度,任务的名字,以及 state 状态。

五、Sink

  Flink 没有类似于spark中foreach方法,让用户进行迭代的操作。虽有对外的输出操作都要利用Sink完成。最后通过类似如下方式完成整个任务最终输出操作。

1,kafka

dstream.addSink(new FlinkKafkaProducer011[String]("linux01:9092","test", new SimpleStringSchema()))

2,redis

<dependency>
<groupId>org.apache.bahir</groupId>
<artifactId>flink-connector-redis_2.</artifactId>
<version>1.0</version>
</dependency>
val config = new FlinkJedisPoolConfig.Builder().setHost("127.0.0.1").setPort().build()
resultDStream.addSink(new RedisSink[Item](config,new MyRedisMapper))
//定义redisMapper
class MyRedisMapper extends RedisMapper[Item] {
override def getCommandDescription: RedisCommandDescription = {
new RedisCommandDescription(RedisCommand.HSET,"item_test") //hkey
}
override def getKeyFromData(data: Item): String = data.id
override def getValueFromData(data: Item): String = data.toString
}

3,Elasticsearch

<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-elasticsearch6_2.</artifactId>
<version>1.7.</version>
</dependency>
//定义es的host集合
val list = new util.ArrayList[HttpHost]()
list.add(new HttpHost("linux01", ))
//定义esBuilder
val esBuilder = new ElasticsearchSink.Builder[Item](list,new ElasticsearchSinkFunction[Item] {
override def process(element: Item, ctx: RuntimeContext, indexer: RequestIndexer): Unit = {
//定义es数据存储方式和存储值
val json = new util.HashMap[String, String]()
json.put("data", element.toString)
//定义存储索引 type 和数据源
val indexRequest = Requests.indexRequest().index("indexName").`type`("_doc").source(json)
indexer.add(indexRequest)
}
})
resultDStream.addSink(esBuilder.build())

4,自定义sink(JDBC)

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.</version>
</dependency>
resultDStream.addSink(new MyJDBCSink)
//自定义jdbcsink
class MyJDBCSink extends RichSinkFunction[Sensor]{
var conn: Connection = _
var insertStmt: PreparedStatement = _
var updateStmt: PreparedStatement = _
//open 简历连接
override def open(parameters: Configuration): Unit = {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "")
insertStmt = conn.prepareStatement("INSERT INTO item_test (id, num) VALUES (?, ?)")
updateStmt = conn.prepareStatement("UPDATE item_test SET num = ? WHERE id = ?")
}
//调用执行
override def invoke(value: Sensor, context: SinkFunction.Context[_]): Unit = {
updateStmt.setDouble(, value.temp)
updateStmt.setString(, value.id)
updateStmt.execute()
if (updateStmt.getUpdateCount == ) {
insertStmt.setString(, value.id)
insertStmt.setDouble(, value.temp)
insertStmt.execute()
}
}
//关闭资源
override def close(): Unit = {
insertStmt.close()
updateStmt.close()
conn.close()
}
}

Flink的流处理API(二)的更多相关文章

  1. Flink 从0到1学习—— 分享四本 Flink 国外的书和二十多篇 Paper 论文

    前言 之前也分享了不少自己的文章,但是对于 Flink 来说,还是有不少新入门的朋友,这里给大家分享点 Flink 相关的资料(国外数据 pdf 和流处理相关的 Paper),期望可以帮你更好的理解 ...

  2. 如何在 Apache Flink 中使用 Python API?

    本文根据 Apache Flink 系列直播课程整理而成,由 Apache Flink PMC,阿里巴巴高级技术专家 孙金城 分享.重点为大家介绍 Flink Python API 的现状及未来规划, ...

  3. 《基于Apache Flink的流处理》读书笔记

    前段时间详细地阅读了 <Apache Flink的流处理> 这本书,作者是 Fabian Hueske&Vasiliki Kalavri,国内崔星灿翻译的,这本书非常详细.全面得介 ...

  4. Flink在流处理上常见的Source和sink操作

    flink在流处理上的source和在批处理上的source基本一致.大致有4大类 1.基于本地集合的source(Collection-based-source) 2.基于文件的source(Fil ...

  5. flink的流处理特性

    flink的流处理特性: 支持高吞吐.低延迟.高性能的流处理 支持带有事件时间的窗口(Window)操作 支持有状态计算的Exactly-once语义 支持高度灵活的窗口(Window)操作,支持基于 ...

  6. Flink的DataSource三部曲之二:内置connector

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  7. Flink的sink实战之二:kafka

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  8. Civil 3D API二次开发学习指南

    Civil 3D构建于AutoCAD 和 Map 3D之上,在学习Civil 3D API二次开发之前,您至少需要了解AutoCAD API的二次开发,你可以参考AutoCAD .NET API二次开 ...

  9. 用JSON-server模拟REST API(二) 动态数据

    用JSON-server模拟REST API(二) 动态数据 上一篇演示了如何安装并运行 json server , 在这里将使用第三方库让模拟的数据更加丰满和实用. 目录: 使用动态数据 为什么选择 ...

随机推荐

  1. AIX系统下挂载外置存储

    连接盘柜后在盘柜里映射好分区. 1.扫描硬件才能发现盘柜映射的容量 ,命令cfgmgr 2.查看在 AIX 系统下能否认到盘柜的分区. 命令:lsdev -Cc disk 3.查看物理卷(pv),命令 ...

  2. element-ui(vue版)使用switch时change回调函数中的形参传值问题

    需求说明 有多个switch组件 需要知道switch的状态 表格中当前行(scope.row)的数据 问题描述 官方文档中对switch中change的描述: 目前能得到switch的状态值,但是无 ...

  3. Scala 基础(六):Scala变量 (三) 标识符

    1 标识符概念 1) Scala 对各种变量.方法.函数等命名时使用的字符序列称为标识符 2) 凡是自己可以起名字的地方都叫标识符 2 标识符的命名规则 Scala中的标识符声明,基本和Java是一致 ...

  4. Mysql基础(三):MySQL基础数据类型、完整性约束、sql_mode模式

    目录 2.MySQL基础数据类型.完整性约束.sql_mode模式 1. MySQL常用数据类型 2. 完整性约束 3. MySQL的sql_mode模式说明以及设置 2.MySQL基础数据类型.完整 ...

  5. 数据可视化之powerBI基础(一) 如何查看PowerBI图表背后的数据

    https://zhuanlan.zhihu.com/p/64405494 图表很直观,但有时候我们不仅想看图,也想更进一步查看生成该图表的明细数据,在PowerBI中有三种方式. (一)在图表上单击 ...

  6. 数据可视化之PowerQuery篇(十二)客户购买频次分布

    https://zhuanlan.zhihu.com/p/100070260 商业数据分析通常都可以简化为对数据进行筛选.分组.汇总的过程,本文通过一个实例来看看PowerBI是如何快速完成整个过程的 ...

  7. IDEA搭建SpringMVC简单接口框架(Maven项目)

    1, 新建项目,选择Maven,如图一次选择,最后点击Next 2, 输入GroupId和ArtifactId,点击Next 3,根据需要选择自定义maven配置,点击Next.(①可以直接跳过) 4 ...

  8. Java8——方法引用

    方法引用就是通过类名或方法名引用已经存在的方法来简化lambda表达式.那么什么时候需要用方法引用呢?如果lamdba体中的内容已经有方法实现了,我们就可以使用方法引用. 一.方法引用的三种语法格式 ...

  9. spring boot实现简单的登录拦截

    一.思路 1.在pom.xml导入相关包 2.先写个简单的认证适配器(WebSecurityConfig extends WebSecurityConfigurerAdapter),登录拦截后就会跳转 ...

  10. Ethical Hacking - GAINING ACCESS(17)

    CLIENT SIDE ATTACKS - Backdooring exe' s Download an executable file first. VEIL - FRAMEWORK A backd ...