package api
import org.apache.flink.streaming.api.functions.ProcessFunction
import org.apache.flink.streaming.api.scala._
import org.apache.flink.util.Collector
/**
*
* @PROJECT_NAME: Flink
* @PACKAGE_NAME: api
* @author: 赵嘉盟-HONOR
* @data: 2025-5-15 21:24
* @DESCRIPTION
*
*/
object SideOutput {
def main(args: Array[String]): Unit = {
val env=StreamExecutionEnvironment.getExecutionEnvironment
val inputStream=env.socketTextStream("localhost",7777)
val dataStream=inputStream
.map( data=>{
val arr=data.split(",")
SensorReading(arr(0),arr(1).toLong,arr(2).toDouble)
})
val highTempStream=dataStream
.process( new SplitTempProcessor(30.0))
highTempStream.print("high")
highTempStream.getSideOutput(new OutputTag[(String,Long,Double)]("low")).print("low")
env.execute("side output")
}
}
//实现自定义ProcessFunction,实现分流
class SplitTempProcessor(threshold:Double) extends ProcessFunction[SensorReading,SensorReading] {
override def processElement(i: SensorReading, context: ProcessFunction[SensorReading, SensorReading]#Context, collector: Collector[SensorReading]): Unit = {
//判断条件
if (i.temperature > threshold) {
//主输出
collector.collect(i)
} else {
//侧输出流
context.output(new OutputTag[(String, Long, Double)]("low"), (i.id, i.timestamp, i.temperature))
}
}
}
这段代码是一个基于 Apache Flink 的流处理程序,主要功能是通过 ProcessFunction 实现数据的分流处理,将传感器数据根据温度阈值分为主输出流和侧输出流。
1. 代码结构总结
主要功能模块
- 数据源读取:
- 从 Socket 读取数据流(
localhost:7777
),数据格式为id,timestamp,temperature
。
- 从 Socket 读取数据流(
- 数据处理:
- 使用
map()
方法将输入数据转换为SensorReading
对象。 - 使用自定义的
ProcessFunction
实现数据分流,根据温度阈值将数据分为主输出流和侧输出流。
- 使用
- 数据输出:
- 主输出流(温度高于阈值)直接输出到控制台。
- 侧输出流(温度低于或等于阈值)通过
OutputTag
输出到控制台。
核心类与方法
SensorReading
:- 样例类,用于表示传感器的数据(ID、时间戳、温度)。
ProcessFunction
:- Flink 提供的底层处理函数,可以访问时间、状态等底层功能,并支持侧输出流。
OutputTag
:- 用于标识侧输出流,通过
context.output()
将数据发送到侧输出流。
- 用于标识侧输出流,通过
Collector
:- 用于将数据发送到主输出流。
2. 代码原理拓展
Flink 流处理的核心概念
-
数据源(Source):
代码中从 Socket 读取数据流,Flink 还支持从 Kafka、文件、集合等数据源读取数据。 -
数据处理(Transformation):
ProcessFunction
是 Flink 提供的底层处理函数,可以访问时间、状态等底层功能。通过processElement()
方法对每条数据进行处理,并根据条件将数据发送到主输出流或侧输出流。 -
侧输出流(Side Output):
侧输出流是 Flink 提供的一种机制,用于将数据分流到多个输出流。通过OutputTag
标识侧输出流,并通过context.output()
将数据发送到侧输出流。 -
数据输出(Sink):
代码中使用print()
方法将数据输出到控制台,Flink 还支持将数据输出到文件、Kafka、数据库等目标。
3. 代码优化与扩展
优化建议
-
异常处理:
在数据处理过程中增加异常处理逻辑,避免程序因异常数据而崩溃。 -
配置管理:
将温度阈值、Socket 地址等配置提取到外部配置文件(如application.conf
),便于维护。 -
并行度设置:
根据数据量和硬件资源,设置合适的并行度,以提高程序性能。
功能扩展
-
复杂条件分流:
在ProcessFunction
中实现更复杂的分流逻辑,例如根据多个字段的组合条件进行分流。 -
时间窗口计算:
结合 Flink 的时间窗口功能,对数据进行滑动窗口或滚动窗口计算。 -
状态管理:
使用 Flink 的状态管理功能,记录历史数据或统计信息,实现更复杂的业务逻辑。 -
数据写入到外部存储:
将主输出流和侧输出流的数据写入到数据库(如 MySQL、HBase)或文件系统(如 HDFS)。
4. 示例代码扩展
以下是一个扩展示例,展示如何将数据写入到文件系统:
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.connectors.fs.bucketing.BucketingSink
import org.apache.flink.streaming.connectors.fs.StringWriter
object ExtendedSideOutput {
def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
// 从 Socket 读取数据流
val inputStream = env.socketTextStream("localhost", 7777)
// 转换为 SensorReading 对象
val dataStream = inputStream.map(data => {
val arr = data.split(",")
SensorReading(arr(0), arr(1).toLong, arr(2).toDouble)
})
// 自定义 ProcessFunction 实现分流
val highTempStream = dataStream.process(new SplitTempProcessor(30.0))
// 主输出流写入到文件系统
val highTempSink = new BucketingSink[SensorReading]("hdfs://hadoop101:9000/flink/high")
highTempSink.setWriter(new StringWriter())
highTempSink.setBatchSize(1024 * 1024 * 100) // 每 100MB 生成一个文件
highTempStream.addSink(highTempSink)
// 侧输出流写入到文件系统
val lowTempSink = new BucketingSink[(String, Long, Double)]("hdfs://hadoop101:9000/flink/low")
lowTempSink.setWriter(new StringWriter())
lowTempSink.setBatchSize(1024 * 1024 * 100) // 每 100MB 生成一个文件
highTempStream.getSideOutput(new OutputTag[(String, Long, Double)]("low")).addSink(lowTempSink)
env.execute("ExtendedSideOutput")
}
}
5. 总结
- 核心功能:
- 通过
ProcessFunction
实现数据分流,将传感器数据根据温度阈值分为主输出流和侧输出流。
- 通过
- 侧输出流机制:
- 使用
OutputTag
和context.output()
实现侧输出流,支持多路数据输出。
- 使用
- 优化与扩展:
- 通过异常处理、配置管理、并行度设置等功能优化程序,通过复杂条件分流、时间窗口计算、状态管理等功能扩展程序。
通过理解 Flink 的核心概念和代码原理,可以更好地开发和优化流处理程序。