需求
kafka中存有从metricbeat收集的各种数据系统指标数据存到同一个topic中,但是各种指标数据不尽相同,这时候需要将相同结构的数据收集到一起分开处理,就用到了Flink的分流操作。
依赖
主要有flink、kafka和解析json的依赖。
<dependencies>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-scala_2.11</artifactId>
<version>1.11.1</version>
</dependency>
<!--缺这个依赖会报错:java.lang.IllegalStateException: No ExecutorFactory found to execute the application.-->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-clients_2.11</artifactId>
<version>1.11.1</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-kafka-0.10_2.11</artifactId>
<version>1.11.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
<scope>compile</scope>
</dependency>
</dependencies>
代码
object KafkaDemo {
def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
//得道kafka数据源,addKafkaSource是自己写的函数
val kafkaDS = addKafkaSource(env, "kafka-flink")
//使用ProcessFunction进行分流操作
val splitedDS = kafkaDS.map(JSON.parseObject(_))
.process(new ProcessFunction[JSONObject, JSONObject] {
override def processElement(obj: JSONObject, context: ProcessFunction[JSONObject, JSONObject]#Context, collector: Collector[JSONObject]): Unit = {
//首先需要判断存在才能去解析
if(obj.containsKey("process") && obj.getJSONObject("process").containsKey("name")) {
//使用模式匹配进行操作,下面有idea/Google Chrome H/Mac OS X/metricbeat等多个服务,这里解析到的被放到了侧输出流
obj.getJSONObject("process").getString("name") match {
//注意OutputTag对象是有泛型的
case "idea" => context.output(new OutputTag[JSONObject]("idea"), obj)
case "Google Chrome H" => context.output(new OutputTag[JSONObject]("Google Chrome H"), obj)
case "Mac OS X" => context.output(new OutputTag[JSONObject]("Mac OS X"), obj)
case "metricbeat" => context.output(new OutputTag[JSONObject]("metricbeat"), obj)
case "JavaApplication" => context.output(new OutputTag[JSONObject]("JavaApplication"), obj)
case _ => collector.collect(obj)
}
} else {
//解析不到的被放到了主输出流
context.output(new OutputTag[JSON]("unknown"),obj)
}
}
})
//主输出流可以直接print
// splitedDS.print()
//侧输出流需要使用getSideOutput获取
splitedDS.getSideOutput(new OutputTag[JSONObject]("unknown"))
.print()
env.execute("process function demo")
}
}
总结
process function的功能当然还有很多,是flink中非常强大的函数。
侧输出流的功能想了一下Spark是不是没办法实现呢?如果有大佬想到了使用Spark实现的方式记得留言呀。