作业描述:
针对当前空⽓质量监测数据,环保部门需要根据监测数据实时发布预警信息,需要我们在实时到达的六种污染物监测数据中,根据每⼀种数据的监测值进⾏报警检测。
输⼊数据:“空⽓质量监控数据”,格式如下:
Time, id, PM2.5, PM10, SO2, CO, NO2, O3
例如:2017-10-26 10:10:10.666,1,160,260,400,50,1000,300
输出结果格式如下:
Time | id | Type | Value
⽰例 :Time| id | PM2.5 | 400
报警规则:
- PM2.5>=150
- PM10>=350
- SO2>=800
- CO>=60
- NO2>=1200
- O3>=400
开发环境:
- Spark Streaming
- Scala
- IDEA + Maven
- Mac
实现思路:
我简单的说一下我的实现思路:在这之前,你必须要知道什么流处理,因为Spark Streaming就是基于流处理的,如果你对流处理还不清楚的,请先百度学习一下什么是流处理。如果你想百度,我简单的解释一下流处理的意思。大概意思就是数据像水一样,是时时流动的,时时产生的;不像HDFS,数据是提前放到文件夹下,然后再去读写。例如sokect中的数据就是这样的。因此,在Spark Streaming中只少需要开启一个线程去检测是否有数据流进来。清楚了流处理方式后,下面就很简单了。使用Spark Streamng开启一个线程去时时检测socket的某个端口(我检测的端口是是9999),然后将获取到的数据转化成DStream对象,在通过FlatMap操作将数据进行切分生成新的DStream,再通过foreachRDD遍历所有切分好的DStream将他们转化成Array类型赋值给AirQuality对象,最后在AirQuality对象中做空气质量的判断。以上就是整体的实现思路了。还是很简单的。
开启scoket端口
nc -lk 9999
下面看一下maven的pom.xml配置:
<dependencies>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId> spark-core_2.11</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_2.11</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
下面是具体的实现:
class AirQuality(time:String,id:Int,PM2_5:Int,PM10:Int,SO2:Int,CO:Int,NO2:Int,O3:Int) {
def calculateAirQuality:Unit = {
if (this.id == 0){
return
}
//空气质量检测
if (this.PM2_5 >= 150) {
this.printResult("PM2.5",this.PM2_5)
}
if (this.PM10 >= 350) {
this.printResult("PM10",this.PM10)
}
if(this.SO2 >= 800){
this.printResult("SO2",this.SO2)
}
if(this.CO >= 60){
this.printResult("CO",this.CO)
}
if(this.NO2 >= 1200){
this.printResult("NO2",this.NO2)
}
if(this.O3 >= 400) {
this.printResult("O3", this.O3)
}
}
def printResult(key:String,value:Int):Unit = {
val result = this.time + " | " + this.id + " | " + key + " | " + value
println(result)
}
}
object AirQuality {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("local[2]").setAppName("AirQuality")
val ssc = new StreamingContext(conf,Seconds(1))
//从socket端口读取数据,返回的是ReceiverInputDStream
val receiverInputStream = ssc.socketTextStream("localhost",9999);
//对返回的是ReceiverInputDStream操作,进行切分数据,生成DStream
val words = receiverInputStream.flatMap(line => line.split(","))
words.foreachRDD(rdd => {
val arr = rdd.collect()
if (arr.length > 7) {
val airQuality = new AirQuality(
arr(0),
arr(1).trim.toInt,
arr(2).trim.toInt,
arr(3).trim.toInt,
arr(4).trim.toInt,
arr(5).trim.toInt,
arr(6).trim.toInt,
arr(7).trim.toInt)
airQuality.calculateAirQuality
}
})
ssc.start()
ssc.awaitTermination()
}
}
输入数据
2017-10-26 10:10:10.666,1,160,260,400,50,1000,300
2017-10-26 10:10:10.666,1,140,360,400,50,1000,300
2017-10-26 10:10:10.666,1,140,260,900,50,1000,300
2017-10-26 10:10:10.666,1,140,260,400,70,1000,300
2017-10-26 10:10:10.666,1,140,260,400,50,1200,300
2017-10-26 10:10:10.666,1,140,260,400,50,1000,500
2017-10-26 10:10:10.666,1,160,360,900,70,1200,500
输出数据
2017-10-26 10:10:10.666 | 1 | PM2.5 | 160
…….