1.wordcount

利用socket作为数据源,对输入的每行数据进行单词计数。计算频率为process time的每10秒一次,结果输出到terminal。

  1. object SocketWindowWordCount {
  2. def main(args: Array[String]) : Unit = {
  3. val port: Int = try {
  4. ParameterTool.fromArgs(args).getInt("port")
  5. } catch {
  6. case e: Exception => {
  7. System.err.println("No port specified. Please run 'xx.jar --port <port>'")
  8. return
  9. }
  10. }
  11. val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
  12. val text = env.socketTextStream("localhost", port, '\n')
  13. val windowCounts = text
  14. .flatMap(_.split("\\s"))
  15. .map(WordWithCount(_,1))
  16. .keyBy(_.word)
  17. .window(TumblingProcessingTimeWindows.of(Time.seconds(10)))
  18. .sum("count")
  19. windowCounts.print()
  20. env.execute("Socket Window WordCount")
  21. }
  22. case class WordWithCount(word: String, count: Long)
  23. }

数据格式

  1. case class SensorReading(id: String, timestamp: Long, temperature: Double)
  2. object SmokeLevel extends Enumeration {
  3. type SmokeLevel = SmokeLevel.Value
  4. val High, Low = Value
  5. }
  6. case class Alert(message: String, timestamp: Long)

2.双流警报EventTime

时间特征为event time,每1s更新一次watermark,watermark由SensorReading内部的timestamp推进,允许5s的延迟(过滤掉迟到数据)。数据源SensorReading并发处理,数据源SmokeLevel并发度为1,但能够被每个并发的SensorReading流访问。假设两个流的数据是源源不断的。当SensorReading的temperature大于100且SmokeLevel为High时触发警报。警报包含当时SensorReading的timestamp。

下面例子,迟到数据,即数据晚于WM依然会被处理

注意:如果某个流在connect前assignTimestampsAndWatermarks,connect后的流是不会更新WM的。

  1. def main(args: Array[String]): Unit = {
  2. val env = StreamExecutionEnvironment.getExecutionEnvironment
  3. env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
  4. env.getConfig.setAutoWatermarkInterval(1000L)
  5. val sensorInput = env
  6. .addSource(new SensorSource)
  7. .assignTimestampsAndWatermarks(
  8. new BoundedOutOfOrdernessTimestampExtractor[SensorReading](Time.seconds(5)) {
  9. override def extractTimestamp(element: SensorReading): Long = {
  10. element.timestamp
  11. }
  12. })
  13. val smokeLevelInput = env
  14. .addSource(new SmokeLevelSource)
  15. .setParallelism(1)
  16. val res = sensorInput
  17. .process(new MyKeyedProcessFunction) // 这里的实现省略,其实就是if和collect
  18. .connect(smokeLevelInput)
  19. .flatMap(new MyFlatMapFunc)
  20. res.print()
  21. env.execute("multiple streamss")
  22. }
  23. class MyFlatMapFunc extends CoFlatMapFunction[SensorReading, SmokeLevel, Alert] {
  24. private private var curSmokeLevel = SmokeLevel.Low
  25. override def flatMap1(value: SensorReading, out: Collector[Alert]): Unit = {
  26. if (curSmokeLevel.equals(SmokeLevel.High) && value.temperature > 100) {
  27. out.collect(Alert("Alert! ", value.timestamp))
  28. }
  29. }
  30. override def flatMap2(value: SmokeLevel, out: Collector[Alert]): Unit = {
  31. curSmokeLevel = value
  32. }
  33. }

3.持续计数stateful + timer + SideOutputs

对每个key的数据量进行累加计数,如果1分钟没有新数据,就输出key-count对。对每一个数据进行处理时,sideoutput当前所处理的key的state数据(更新后的)

  1. val realTimeInfo: OutputTag[String] =
  2. new OutputTag[String]("real-time_info")
  3. def main(args: Array[String]): Unit = {
  4. val env = StreamExecutionEnvironment.getExecutionEnvironment
  5. env.getConfig.setAutoWatermarkInterval(1000L)
  6. env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
  7. val countStream = env.addSource(new SensorSource)
  8. .keyBy(_.id)
  9. .process(new MyProcessFunc)
  10. countStream.getSideOutput(realTimeInfo)
  11. .print()
  12. env.execute()
  13. }
  14. case class CountWithTimeStamp(key: String, count: Int, ts: Long)
  15. class MyProcessFunc extends KeyedProcessFunction[String, SensorReading, (String, Int)] {
  16. lazy val state = getRuntimeContext
  17. .getState(new ValueStateDescriptor[CountWithTimeStamp]("muState", classOf[CountWithTimeStamp]))
  18. override def processElement(value: SensorReading,
  19. ctx: KeyedProcessFunction[String, SensorReading, (String, Int)]#Context,
  20. out: Collector[(String, Int)]): Unit = {
  21. val current = state.value() match {
  22. case null =>
  23. CountWithTimeStamp(value.id, 1, ctx.timestamp())
  24. case CountWithTimeStamp(key, count, lastModified) =>
  25. // 删除上一次的timer
  26. ctx.timerService().deleteEventTimeTimer(lastModified + 6000)
  27. CountWithTimeStamp(key, count + 1, ctx.timestamp())
  28. }
  29. state.update(current)
  30. ctx.timerService().registerEventTimeTimer(current.ts + 6000)
  31. ctx.output(realTimeInfo, current)
  32. }
  33. override def onTimer(timestamp: Long,
  34. ctx: KeyedProcessFunction[String, SensorReading, (String, Int)]#OnTimerContext,
  35. out: Collector[(String, Int)]): Unit = {
  36. state.value() match {
  37. case CountWithTimeStamp(key, count, lastModified) =>
  38. if (timestamp == lastModified) out.collect((key, count)) else None
  39. case _ =>
  40. }
  41. }
  42. }

4.一定时间范围内的极值windowfunction + checkpoint

利用tumbling window计算各个sensor在15s内的最大最小值,返回结果包含窗口的结束时间。另外,window只存储极值,不保留原数据。

checkpoint间隔为10s,watermark刷新间隔1s

  1. def main(args: Array[String]): Unit = {
  2. val env = StreamExecutionEnvironment.getExecutionEnvironment
  3. env.getConfig.setAutoWatermarkInterval(1000)
  4. env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
  5. env.enableCheckpointing(10 * 1000L)
  6. env.addSource(new SensorSource)
  7. .assignTimestampsAndWatermarks(new MyPeriodicAssigner)
  8. .map(r => (r.id, r.temperature, r.temperature))
  9. .keyBy(_._1)
  10. .window(TumblingEventTimeWindows.of(Time.seconds(15)))
  11. .reduce(
  12. (item1: (String, Double, Double), item2: (String, Double, Double)) => {
  13. (item1._1, item1._2.min(item2._2), item1._3.max(item2._3))
  14. },
  15. new MyWindowEndProcessFunction()
  16. )
  17. }
  18. case class MaxMinTemperature(key: String, min: Double, max: Double, ts: Long)
  19. class MyWindowEndProcessFunction
  20. extends ProcessWindowFunction[(String, Double, Double), MaxMinTemperature, String, TimeWindow] {
  21. override def process(key: String, context: Context, elements: Iterable[(String, Double, Double)],
  22. out: Collector[MaxMinTemperature]): Unit = {
  23. out.collect(MaxMinTemperature(key, elements.head._2, elements.head._3, context.window.getEnd))
  24. }
  25. }

Flink编程练习的更多相关文章

  1. Flink 编程接口

    欢迎来 kk大数据,今天分享的是 Flink 提供了哪些编程接口可以给我们开发. 一.数据集类型 现实世界中,所有的数据都是以流式的形态产生的,不管是哪里产生的数据,在产生的过程中都是一条条地生成,最 ...

  2. <译>Flink编程指南

    Flink 的流数据 API 编程指南 Flink 的流数据处理程序是常规的程序 ,通过再流数据上,实现了各种转换 (比如 过滤, 更新中间状态, 定义窗口, 聚合).流数据可以来之多种数据源 (比如 ...

  3. Flink 编程模型

    抽象层次   levels_of_abstraction 最低级的抽象接口是状态化的数据流接口(stateful streaming).这个接口是通过 ProcessFunction 集成到 Data ...

  4. 第03讲:Flink 的编程模型与其他框架比较

    Flink系列文章 第01讲:Flink 的应用场景和架构模型 第02讲:Flink 入门程序 WordCount 和 SQL 实现 第03讲:Flink 的编程模型与其他框架比较 本课时我们主要介绍 ...

  5. Flink学习笔记:Flink API 通用基本概念

    本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKhaz ...

  6. flink学习笔记-各种Time

    说明:本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKh ...

  7. 首次尝试Flink的一些感受

    最近打算研究研究 Flink,根据官方文档写个 Hello,World.入门还是比较容易的,不需要复杂的安装环境.配置.这篇文章简单介绍 Flink 的使用感受以及入门. 感受 搭建环境方便:Flin ...

  8. Flink入门宝典(详细截图版)

    本文基于java构建Flink1.9版本入门程序,需要Maven 3.0.4 和 Java 8 以上版本.需要安装Netcat进行简单调试. 这里简述安装过程,并使用IDEA进行开发一个简单流处理程序 ...

  9. Flink入门介绍

    什么是Flink Apache Flink是一个分布式大数据处理引擎,可以对有限数据流和无限数据流进行有状态计算.可部署在各种集群环境,对各种大小的数据规模进行快速计算. Flink特性 支持高吞吐. ...

随机推荐

  1. WIndows 系统下的常用命令 和 检测方法

    ### 一.检测硬盘速度(Windows 自带工具) #### 使用windows 系统自带的工具测试硬盘读写速度 > 在使用下面命令前,需要获得管理员权限,才会在Dos窗口上显示(否则,一闪而 ...

  2. MySQL4

    MySQL数据库4 1 管理索引 创建索引帮助 help CREATE INDEX 创建索引 指令 CREATE INDEX 语法格式 CREATE INDEX index_name ON tbl_n ...

  3. PHP代码静态分析工具PHPStan

    最近发现自己写的PHP代码运行结果总跟自己预想的不一样,排查时发现大多是语法错误,在运行之前错误已经种下.可能是自己粗心大意,或者说php -l检测太简单,不过的确是有一些语法错误埋藏得太深(毕竟PH ...

  4. Mysql Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column To disable safe mode

    今天用mysql workbench在更新数据的时候,出现了下面错误:15:52:39    update wp_posts set post_content = replace(post_conte ...

  5. xfce 安装文泉驿字体

    下载文泉驿字体 #拷贝字体到目录/usr/share/fonts/wqy#创建字体缓存 mkfontscale # 在当前目录下生成fonts.scale文件 mkfontdir # 在当前目录下生成 ...

  6. 用python写了一个猜年龄小游戏

    写一个猜年龄游戏: 需要实现用户登录的功能 初始用户登录信息为 {'hades': '13579','nick': '123','ruixing': 'a1','fanping': 'b2'} 登录时 ...

  7. LINUX-初始化一个文件系统

    mkfs /dev/hda1 在hda1分区创建一个文件系统 mke2fs /dev/hda1 在hda1分区创建一个linux ext2的文件系统 mke2fs -j /dev/hda1 在hda1 ...

  8. Python-文件和数据格式化

    文件的使用 >文件的类型 文件的理解:文件是数据的抽象和集合 -文件时存储在辅助存储器上的数据序列 -文件是数据存储的一种形式 -文件展现形态:文本文件和二进制文件 文本文件vs.二进制文件 - ...

  9. 如何创建新用户和授予MySQL中的权限

    原创官网http://www.howtoing.com/how-to-create-a-new-user-and-grant-permissions-in-mysql/ 关于MySQL MySQL是一 ...

  10. Leetcode 133.克隆图

    克隆图 克隆一张无向图,图中的每个节点包含一个 label (标签)和一个 neighbors (邻接点)列表 . OJ的无向图序列化: 节点被唯一标记. 我们用 # 作为每个节点的分隔符,用 , 作 ...