一、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. python网络编程01 /C/S架构|B/S架构、网络通信原理、五层协议、七层协议简述、端口映射技术

    python网络编程01 /C/S架构|B/S架构.网络通信原理.五层协议.七层协议简述.端口映射技术 目录 python网络编程01 /C/S架构|B/S架构.网络通信原理.五层协议.七层协议简述. ...

  2. 重学c#系列——c#运行原理(二)

    前言 c# 是怎么运行的呢?是否和java一样运行在像jvm的虚拟机上呢?其实差不多,但是更广泛. c# 运行环境不仅c#可以运行,符合.net framework 开发规范的都可以运行. c# 程序 ...

  3. AI开发利器:HiLens Studio技术解读

    摘要:传统的AI应用开发和部署意味着高成本和高门槛,借助HiLens Studio,AI应用开发和部署仅需要三步. 曾几何时, 在我们青春年少时, 当我们看到某篇AI的技术文章时, 心中总不免想要在一 ...

  4. three.js 曲线

    上几篇说了three.js的曲线,这篇来郭先生来说说three.js曲线,在线案例点击郭先生的博客查看. 1. 了解three.js曲线 之前已经说了一些three.js的几何体,这篇说一说three ...

  5. 【Nginx】如何配置Nginx日志?这是最全面的一篇了!!

    写在前面 日志对于统计排错来说非常有利的.本文总结了 Nginx 日志相关的配置如 access_log. log_format.open_log_file_cache. log_not_found. ...

  6. Cyber Security - Palo Alto Firewall Objects Addresses, Services, and Groups(3)

    LDAP Authentication and Remote Users and Groups Create Remote User Objects and LDAP Integration: sam ...

  7. Ethical Hacking - GAINING ACCESS(20)

    CLIENT SIDE ATTACKS - Spoofing backdoor extension Change the extension of the trojan from exe to a s ...

  8. Python Ethical Hacking - VULNERABILITY SCANNER(7)

    VULNERABILITY_SCANNER How to discover a vulnerability in a web application? 1. Go into every possibl ...

  9. Spring框架零基础学习(一):IOC|DI、AOP

    文章目录 一.IDEA创建Spring项目 二.Spring: IOC和DI 三.Spring: AOP 参考链接: HOW2J.CN:Spring idea创建一个spring项目 一.IDEA创建 ...

  10. vs coed的使用(二) 如何运行cpp文件(不用插件比如code runner)

    一.前提 1.配置好编译运行的环境,比如系统变量.vs code的settings.json 2.检查配置好的环境没有问题 我配置结果 [环境变量] [系统变量] 确定settings.json里面的 ...