Flink 周练习(二)
数据文件——链接: https://pan.baidu.com/s/1M9M_4eupYEHHfXS0HdiO8g?pwd=p3nx 提取码: p3nx 复制这段内容后打开百度网盘手机App,操作更方便哦
用户行为数据集,保存为 UserBehavior.csv文件。本数据集包含了某宝上某一天随机一百万用户的所有行为(包括点击pv、购买buy、收藏cart、喜欢fav)。
数据集的每一行表示一条用户行为,由用户 ID、商品 ID、商品类目 ID、行为类型和时间戳组成,并以逗号分隔。关于数据集中每一列的详细描述如下: 字段名 数据类型 说明 userId Long 加密后的用户 ID itemId Long 加密后的商品 ID categoryId Int 加密后的商品所属类别 ID behavior String 用户行为类型,包括(‘pv’,‘buy’, ‘cart’, ‘fav’) timestamp Long 行为发生的时间戳,单位秒 完成以下功能: 1.创建kafka主题 创建kafka主题userHavior,分区数量2和备份数量2 2.创建工程 包名为com.姓名首字母,代码规范,注释清晰 3.使用Scala或者Java完成以下功能 读取UserBehavior.csv,使用kafka生产者发送到userHavior主题 4.完成实时热门商品统计 1)创建Flink流式处理环境,并设置时间语义为事件时间 2)设置并行度为1 3)正确消费kafka数据并封装为样例类 4)抽取事件时间 5)过滤点击行为数据(pv) 6)设置窗口滑动:每5分钟统计最近一个小时的点击量 7)要求使用AggregateFunction增量聚合每个商品的点击次数 8)统计每个窗口每个商品的点击次数,要求展示字段:窗口结束时间,商品id,点击次数 9)过滤商品点击次数大于10的信息 10)将结果sink到新的kafka主题中,主题自选 11)代码清晰,注释完美
KafKa Producer
import org.apache.kafka.clients.producer.KafkaProducer import org.apache.kafka.clients.producer.ProducerRecord import java.util.Properties import scala.io.{BufferedSource, Source} object KafkaProducer { def main(args: Array[String]): Unit = { //读取UserBehavior.csv,使用kafka生产者发送到userHavior主题(8分) val stream: BufferedSource = Source.fromFile("D:\\soft code\\bigdata\\zhuanwu\\my_zcb\\filk\\data\\UserBehavior.csv") val props = new Properties() props.put("bootstrap.servers", "hdp1:9092,hdp2:9092,hdp3:9092") props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer") props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer") val producer = new KafkaProducer[String,String](props) for (i <- stream.getLines()) { producer.send(new ProducerRecord[String, String]("userHavior","", i)) } producer.close() } }
KafKa Consumber
import org.apache.flink.api.common.functions.AggregateFunction import org.apache.flink.api.common.serialization.SimpleStringSchema import org.apache.flink.streaming.api.scala._ import org.apache.flink.streaming.api.scala.function.WindowFunction import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows import org.apache.flink.streaming.api.windowing.time.Time import org.apache.flink.streaming.api.windowing.windows.TimeWindow import org.apache.flink.streaming.connectors.kafka.{FlinkKafkaConsumer, FlinkKafkaProducer, KafkaSerializationSchema} import org.apache.flink.util.Collector import org.apache.kafka.clients.producer.ProducerRecord import java.nio.charset.StandardCharsets import java.util.Properties object KafkaConsumer { def main(args: Array[String]): Unit = { //1)创建Flink流式处理环境,并设置时间语义为事件时间(8分) val env = StreamExecutionEnvironment.getExecutionEnvironment //2)设置并行度为1(4分) env.setParallelism(1) //3)正确消费kafka数据并封装为样例类(8分) val properties = new Properties() properties.setProperty("bootstrap.servers", "hdp1:9092,hdp2:9092,hdp3:9092") properties.setProperty("group.id", "group1") val stream: DataStream[UserBehavior] = env.addSource(new FlinkKafkaConsumer[String]("userHavior", new SimpleStringSchema(), properties)) .map(s=>{ val ss = s.split(",") UserBehavior(ss(0).trim.toLong,ss(1).trim.toLong,ss(2).trim.toInt,ss(3).trim,ss(4).trim.toLong) }) //抽取事件时间(8分) val dataDS: DataStream[UserBehavior] = stream.assignAscendingTimestamps(_.timestamp * 1000) //5过滤点击行为数据(pv .filter(_.behavior.equals("pv")) //设置窗口滑动:每5分钟统计最近一个小时的点击量 val windowDS: DataStream[UserBehaviorCount] = dataDS .keyBy(_.itemId) .window(TumblingEventTimeWindows.of(Time.hours(1), Time.minutes(5))) .aggregate(new MyAggreate, new MyWindow) windowDS.print("每5分钟统计最近一个小时的点击量:") //过滤商品点击次数大于10的信息 val resDS: DataStream[UserBehaviorCount] = windowDS.filter(_.count > 10) //将结果sink到新的kafka主题中,主题自选 val serializationSchema = new KafkaSerializationSchema[String] { override def serialize(element: String, timestamp: java.lang.Long): ProducerRecord[Array[Byte], Array[Byte]] = new ProducerRecord[Array[Byte], Array[Byte]]( "test", // target topic element.getBytes(StandardCharsets.UTF_8)) // record contents } val myProducer = new FlinkKafkaProducer[String]( "test", // target topic serializationSchema, // serialization schema properties, // producer config FlinkKafkaProducer.Semantic.EXACTLY_ONCE) // fault-tolerance resDS.map(_.toString).addSink(myProducer) //执行 env.execute() } } //样例类 case class UserBehavior(userId:Long,itemId:Long,categoryId:Int,behavior:String,timestamp:Long) //要求使用AggregateFunction增量聚合每个商品的点击次数 //In ACC Out class MyAggreate extends AggregateFunction[UserBehavior,Int,Int] { override def createAccumulator(): Int = 0 override def add(in: UserBehavior, acc: Int): Int = acc + 1 override def merge(acc: Int, acc1: Int): Int = acc + acc1 override def getResult(acc: Int): Int = acc } //输出格式的样例类 case class UserBehaviorCount(start:Long,end:Long,key:Long,count:Int) //统计每个窗口每个商品的点击次数,要求展示字段:窗口结束时间,商品id,点击次数 //Int Out Key W class MyWindow extends WindowFunction[Int,UserBehaviorCount,Long,TimeWindow] { override def apply(key: Long, window: TimeWindow, input: Iterable[Int], out: Collector[UserBehaviorCount]): Unit = { for (elem <- input) { out.collect(UserBehaviorCount(window.getStart,window.getEnd,key,elem)) } } }
我有一杯酒,足以慰风尘。