自定义数据源需要继承Receiver,并实现onStart、onStop方法
package com.spark.receiver
import java.io.{BufferedReader, InputStreamReader}
import java.net.Socket
import java.nio.charset.StandardCharsets
import org.apache.log4j.{Level, Logger}
import org.apache.spark.SparkConf
import org.apache.spark.storage.StorageLevel
import org.apache.spark.streaming.{Seconds, StreamingContext}
import org.apache.spark.streaming.receiver.Receiver
/**
* 使用自定义的数据源采集数据
*/
object FileStream {
def main(args: Array[String]): Unit = {
Logger.getLogger("org").setLevel(Level.ERROR)
// 1.初始化Spark配置信息
val conf: SparkConf = new SparkConf().setAppName(this.getClass.getSimpleName).setMaster("local[*]")
// 2.初始化SparkStreamingContext
val ssc = new StreamingContext(conf, Seconds(5))
// 3.创建自定义receiver的Streaming
val lineStream = ssc.receiverStream(new CustomerReceiver("localhost", 9999))
// 4.将每一行数据做切分,形成一个个的单词
val wordStreams = lineStream.flatMap(_.split(" "))
// 5.将单词映射为元组(word, 1)
val wordAndOneStreams = wordStreams.map((_, 1))
// 6.将相同的单词次数做统计
val wordAndCountStreams = wordAndOneStreams.reduceByKey(_+_)
// 7.打印
wordAndCountStreams.print()
// 8.启动SparkStreamingContext
ssc.start()
ssc.awaitTermination()
}
}
/**
* 自定义数据源,实现监控某个端口号,获取该端口号内容
* 需要继承Receiver,并实现onStart、onStop方法来自定义数据源采集
*/
class CustomerReceiver(host: String, prot: Int) extends Receiver[String](StorageLevel.MEMORY_ONLY) {
/*
* 最初启动的时候,调用该方法
* 作用:读数据并将数据发送给Spark
*/
override def onStart(): Unit = {
new Thread("Socket Receiver") {
override def run() {
receive()
}
}.start()
}
/*
* 读数据并将数据发送给Spark
*/
def receive(): Unit = {
// 创建一个Socket
var socket: Socket = new Socket(host, prot)
// 定义一个变量,用来接收端口传过来的数据
var input: String = null
// 创建一个BufferedReader用于读取端口传来的数据
val reader = new BufferedReader(new InputStreamReader(socket.getInputStream, StandardCharsets.UTF_8))
// 读取数据
input = reader.readLine()
// 当receiver没有关闭并且输入数据不为空,则循环发送数据给Spark
while(!isStopped() && input != null) {
// store():将接收到的单个数据存储到Spark的内存中。这些单独的项目将被聚集在一起成为数据块之前被推入Spark的记忆
store(input)
input = reader.readLine()
}
// 跳出循环则关闭资源
reader.close()
socket.close()
// 重启任务
restart("restart")
}
/*
* 当接受方停止时,系统将调用此方法。所有的资源在onStart()中设置的(线程、缓冲区等)必须在这个方法中清除
*/
override def onStop(): Unit = ???
}