1、参考官网地址
http://spark.apache.org/docs/latest/streaming-custom-receivers.html
2、Spark 自定义Receiver
SparkStreaming 能够接收任意类型的流式数据,不单单只是内建的Flume,Kafka,Kinesis,files,sockets等等。当然若要支持此种数据,则需要开发者自定义程序来接受对
应的数据源。本文以下部分就是要实现自定义的Receiver
3、自定义Receiver
3-1) 自定义一个类,通常需要继承原有的基类,在这里需要继承自Receiver,该虚基类有两个方法需要重写分别是
onstart() 接收器开始运行时触发方法,在该方法内需要启动一个线程,用来接收数据。
onstop() 接收器结束运行时触发的方法,在该方法内需要确保停止接收数据。
当然在接收数据流过程中也可能会发生终止接收数据的情况,这时候onstart内可以通过isStoped()来判断 ,是否应该停止接收数据
3-2)数据存储
一旦接收完数据,则必须要进行数据的存储,并交由SparkStreaming 来处理,Spark以store(data)方法来支持此流程。由于数据格式的不同,当然store方法必须要
支持各种类型的数据存储。store方法是以一次存储一条记录或者一次性收集全部的序列化对象。
3-3)注意事项
在Receiver中任何的异常都需要捕获并正确得当地处理,以防止出现故障而不被发现。故障发生后receiver提供了restart(exception)方法用来重新启动该Receiver,
重启过称为,异步调用onStop方法,然后调用onstart方法重新接收消息。当然也会提供直接停止接收的方法,stop(exception) 调用该方法后会同步调用onStop方法,
并终止接收数据流。spark中还提供了reportError(Exception)方法,用来将错误信息发送给Driver端,但是只是简单的上报错误,并没有调用onstop或者onstart方法。
4、自定义代码
class MyReceiver(host: String, port: Int) extends Receiver[String](StorageLevel.MEMORY_AND_DISK_2){
override def onStart() {
// Start the thread that receives data over a connection
new Thread("Socket Receiver") {
override def run() { receive() }
}.start()
}
override def onStop() {
// There is nothing much to do as the thread calling receive()
// is designed to stop by itself if isStopped() returns false
}
/** Create a socket connection and receive data until receiver is stopped */
private def receive() {
var socket: Socket = null
var userInput: String = null
try {
// Connect to host:port
socket = new Socket(host, port)
// Until stopped or connection broken continue reading
val reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8))
userInput = reader.readLine()
while(!isStopped && userInput != null) {
store(userInput)
userInput = reader.readLine()
}
reader.close()
socket.close()
// Restart in an attempt to connect again when server is active again
restart("Trying to connect again")
} catch {
case e: java.net.ConnectException =>
// restart if could not connect to server
restart("Error connecting to " + host + ":" + port, e)
case t: Throwable =>
// restart if there is any other error
restart("Error receiving data", t)
}
}
}
5、使用自定义接收器
val stream = ssc.receiverStream(new MyReceiver("218.193.154.155",9999))
6、可靠以及不可靠接收器
6-1)可靠接收器
对于可靠的数据源,允许发送数据接受并存储成功后被确认。一个可信的接收器,应该对完整接受并存储在Spark中的数据进行确认,并通知消息源接收状态。
通常来说,实现这类接收器需要仔细考虑数据源消息确认语义。
为了实现可靠的接收器,必须使用store(mutiple-records) 来存储数据,这种类型的store属于阻塞式调用,即当所有给定的数据全部存储在Spark后,才会return。
如果接收器设定了存储级别使用replication(默认使用),那么store(mutiple-records)方法将会在所有数据以及备份均完成后才会return,以此保证数据已被Spark可靠
存储,当然接收器可以在这时向数据源发送确认通知。这种机制能够确保所有的数据均被存储而没有被丢失,如果在数据备份过程中发生了错误,那么该数据集将不会
被确认,从而数据源重新发送该数据集直到存储备份成功。
6-2)不可靠接收器
不可靠接收器不会向数据源发送确认消息,这种类型的接收器可以用来接受不支持确认机制的数据源,或者可靠的数据源但是没必要添加消息确认机制。
不可靠接收器只是简单的接收数据,并把它们以一次插入一条记录的模式进行存储,使用store(single-record)方法。这种类型的接收器有如下几点优点:
(1)系统将数据存储为合适大小的数据块
(2)如果接收速率被指定,系统能够进行有效的控制
(3) 实现起来比可靠接收器简单
6-3)总结表
接收器类型 | 特点 |
不可靠接收器 | 实现简单 系统能够控制数据块的生成以及数据的接收速率 没有容错机制,这就导致可能会丢失数据 |
可靠接收器 | 强容错性保障,能够确保零数据丢失率 数据块生成以及接收速率需要通过接收器来实现 实现的复杂程度,取决于数据源的消息确认机制 |