JobGenerator中有一个timer成员,根据配置中的时间间隔不断产生GenerateJobs事件来触发job的产生,以成为job产生的起点。Timer通过clock来作为构建时间的依据。
val clock = {
val clockClass = ssc.sc.conf.get(
"spark.streaming.clock", "org.apache.spark.util.SystemClock")
try {
Utils.classForName(clockClass).newInstance().asInstanceOf[Clock]
} catch {
case e: ClassNotFoundException if clockClass.startsWith("org.apache.spark.streaming") =>
val newClockClass = clockClass.replace("org.apache.spark.streaming", "org.apache.spark")
Utils.classForName(newClockClass).newInstance().asInstanceOf[Clock]
}
}
Clock的默认实现是SystemClock,其实现其实就是调用系统api获得当前时间。
def getTimeMillis(): Long = System.currentTimeMillis()
并实现了waitTillTime()方法用来等待直到目标时间到达。
def waitTillTime(targetTime: Long): Long = {
var currentTime = 0L
currentTime = System.currentTimeMillis()
var waitTime = targetTime - currentTime
if (waitTime <= 0) {
return currentTime
}
val pollTime = math.max(waitTime / 10.0, minPollTime).toLong
while (true) {
currentTime = System.currentTimeMillis()
waitTime = targetTime - currentTime
if (waitTime <= 0) {
return currentTime
}
val sleepTime = math.min(waitTime, pollTime)
Thread.sleep(sleepTime)
}
-1
}
此处实现的细节,并不是计算完毕当前的时间和系统事件的差距而直接进行sleep相应的时间,而是首先计算距离当前时间的十分之一(但不能小于0.025秒),作为单次的最大休眠时间,该线程会不断sleep最大休眠时间与距离目标时间差距时间的小者,以便在分段休眠中达到尽可能精确的目的。
private val timer = new RecurringTimer(clock, ssc.graph.batchDuration.milliseconds,
longTime => eventLoop.post(GenerateJobs(new Time(longTime))), "JobGenerator")
而后在JobGenerator将会把clock作为入参构建一个RecuringTimer,并在这里实现了callback函数用来在达到时间的时候向eventloop发送GenerateJobs事件驱动job生成,生成job的时间间隔也就是在StreamingContext中配置的生成批的间隔。
private def triggerActionForNextInterval(): Unit = {
clock.waitTillTime(nextTime)
callback(nextTime)
prevTime = nextTime
nextTime += period
logDebug("Callback for " + name + " called at time " + prevTime)
}
private def loop() {
try {
while (!stopped) {
triggerActionForNextInterval()
}
triggerActionForNextInterval()
} catch {
case e: InterruptedException =>
}
}
在timer的实现RecuringTimer中,实则实现了一个线程不断调用loop方法,在loop方法中将会调用triggerActionForNextInterval()方法通过上述的clock的waitTillTime()方法在配置好的时间间隔之后触发上文的作为入参传递的callback函数向eventloop发送GenerateJobs事件驱动job生成。