flink学习(3) 流处理API

Environment

getExecutionEnvironment

创建一个执行环境,表示当前执行程序的上下文

批处理使用ExecutionEnvironment调用  流处理使用StreamExecutionEnvironment调用

执行环境的 变量  可以通过 setParalleism设置全局并行度 如果不设置 会以flink-conf。yaml中的配置为准 默认为1

Source

一般先定义输入数据的样例类

case class inputDemo(id:String ,timestamp:Long,temperature:Double)

从集合中取数据 fromCollection

val stream1:DataStream[inputDemo] = env.fromCollection(List(

inputDemo("1",121,35.6),

inputDemo("2",121,31.6)

inputDemo("3",123211,35.64)

inputDemo("4",12311,38.6)

))

打印输出api print  执行计算api   execute  

从文件中读数据 readTextFile

socket文本流 soucketTextStream

从kafka读取数据 需要引入 flink-connector-kafka-011_2.11详见 博客 flink对接kafka

此时需要addSource方法 添加数据源 参数需要传递一个 方法 实现sourceFunction这个接口

连接kafka时 直接 在addSource方法 中

new FlinkKafkaConsumer[类型](topic 名字 ,  反序列化 schema 如String类型 使用 new SimpleStringSchema() ,kafka props)

同样可以自定义source

定义一个class  实现SourceFunction

class mysource() extends SourceFunction[inputDemo]{

var running :Boolean = true

override def cancel():Unit =running =false

 override def run(ctx:SourceFunction.SourceContext[SensorReading]):Unit ={

//通过ctx 发出外部数据源 然后发出去 就构成 自定义source 

ctx.collect  方法 发出数据

}

}

设置slot 共享组  slotSharingGroup( 参数 是 共享组的名称 string类型)

每一个任务 如果没使用该函数 则默认 与上一个使用slotSharingGroup的任务 共享同一个组

flink子任务默认允许共享组

不把任务合并函数 disableChaining()  即之前提到的one-to-one 并行度一样的任务合并 碰到这个函数时 会断开 跟前后都断开

相应的 还有一个startNewChain()表示跟前面断开

相应的 可以在配置 最初的环境时 通过设置环境的变量env调用disableOperatorChaining()的 禁用全局的合并

转换算子 transform 即source到sink之间的所有算子 都算

滚动聚合算子  DataStream 没有聚合操作,目前所有的聚合操作都是针对keyedStream的

 滚动聚合算子 的结果实际上是在状态里存 所以才会出现累积计算的形象

也就是说 必须在做完keyby之后才能用的聚合算子 如 sum count

map 一个输入对应一个输出 数据转换

flatmap 一个输出 对应多个输出 用于打散

filter 过滤筛选

KeyBy  逻辑地将一个流拆分成不相交的分区 每个分区 包含有相同key的元素,在内部以hash的形式实现的 基于hashcode 做分区 同一个key只能在一个分区内处理,一个分区内 可以有不同的key的数据

keyBy 参数 可以传  int 表示字段位置 可以传string 表示样例类的字段名  可以传函数类 函数类 要实现KeySelector 返回 一个 key

class MyIDSelector() extends KeySelector[inputDemo,String]{

override def getKey(value : inputDemo) :String = value.id

}

用完keyby 之后 可以开始用sum count等函数了  sum函数内也是可以传位置 传字段名

其他的 滚动聚合算子 : min()   取这个key里的 min参数里的最小的字段数据 和sql 中min  和 group by 是一个道理

还有一个 minby 就是 直接得到最小的  与key无关 有点像sql中 min套子查询中的min 和 groupby  

逻辑上 类似于 下面这个sql 

select min(tem) from (select min(a) as tem  from t1 group by key) a

reduce 算子 传入的是一个函数  reduce 是每次都在之前聚合的基础上 结合 新数据 得到 新的结果 如果药自定义函数类 的话 类要extends ReduceFunction[类型]  之后 直接 reduce(new  myReduceClass)

aggregate算子 和reduce的区别是 支持操作的是不同类型的 即支持异构,比如输入是 Int 类型,输出可以是 (Int,Int)类型

aggregate定义  是 先聚合每个分区类的元素,然后再整合所有分区的结果,需要预先给定的combine函数和初值

aggregate函数要求设置初值 (zeroValue: U) ,并且有两个函数seqOp和combOp
seqOp对应的是聚合分区内元素的操作
combOp对应的是将所有分区的结果整合起来的操作

num = sc.parallelize([1,2,3,4])
seqOp = (lambda x, y: x[0] + y, x[1] + 1)#<===
combOp = (lambda x, y: x[0] + y[0], x[1] + y[1])#<===
sum = num.aggregate((0,0), seqOp, combOp)
即 分区结果整合 可以和 分区内结果整合 使用两个 函数 而 reduce 分区内结果整合 和分区间结果整合 使用的是同一个函数

分流转换

splict 、side output和 select

val splitStream = dataStream.split(data=> {if(data.a > 1)
    Seq("1")
    else 
    Seq("2")
  })
val oneStream = splitStream.select("1")
val twoStream = splitStream.select("2")
val allStream = splitStream.select("1","2")
//分别输出 data.a >1的数据分别输出 data.a <1的数据  以及全部数据

合流 

connect() 可以搭配colmap colflatmap等方法 实现不同的流不同的处理方式  使用connect后 map 方法 实际上就是colmap 

val warningStream = oneStream.map(
date => (date.id,data.temperature,"aaa")
)
val connectStream:ConnectedStreamswar:[(String,Double,String),inputDemo] warningStream.connect(twoStream)

//此时connectStream调用map falatmap 等算子实际上是调用colmap 需要传两个函数
val resultStream:DataStream[Object] = connectedStreams.map(
warningData =>(warningData._1,warningData._2,"aaa"),
lowtemData => (lowtemData.id,"bb")
)

//其实本质上 是对合流的两个分别做处理 用分流和合流 组合 可以完美实现 if else分支 并实时处理

多流转换算子 split-select connect-comap/coflatmap 成对出现 先转换成 splitStream,ConnectedStreams然后再通过select、 comap转换回datastream 所谓comap 其实就是基于connectedStreams的map方法

Union

单纯的把两个流合在一起 但是不能做分别处理

富函数(RichFunction)

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

rich function 有一个生命周期的概念

典型的有 open()是richfunction的初始化方法 当一个算子被调用前 open会被调用

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

getRuntimeContext()方法提供了函数的RuntimeContext的信息 如执行的并行度,任务名 state状态

复函数 因为可以获取运行时上下文 在运行时 上下文 可以对state进行操作 所以flink的有状态流式计算,做状态编程 就是基于RichFunction的
 

猜你喜欢

转载自blog.csdn.net/a724952091/article/details/106752468