本期内容:

1 数据流生命周期

2 深度思考

  一切不能进行实时流处理的数据都是无效的数据。在流处理时代,SparkStreaming有着强大吸引力,而且发展前景广阔,加之Spark的生态系统,Streaming可以方便调用其他的诸如SQL,MLlib等强大框架,它必将一统天下。

  Spark Streaming运行时与其说是Spark Core上的一个流式处理框架,不如说是Spark Core上的一个最复杂的应用程序。如果可以掌握Spark streaming这个复杂的应用程序,那么其他的再复杂的应用程序都不在话下了。这里选择Spark Streaming作为版本定制的切入点也是大势所趋。

  Receiver在启动的时候是通过ReceiverSupervisor的start方法启动的。

  Receiver接受数据的过程类似于MVC模式: Receiver,ReceiverSupervisor和Driver的关系相当于Model,Control,View,也就是MVC。 Model就是Receiver,存储数据Control,就是ReceiverSupervisor,Driver是获得元数据,也就是View。

  Receiver接受数据流这个的过程:首先会调用ReceiverSupervisor的onStart()方法来启动Receiver。

  然后开启blockPushingThread线程,它将Receiver接受到的将数据写入到BlockManager中。



private val blockPushingThread = new Thread() { override def run() { keepPushingBlocks() } }



  每过一个时间间隔会从队列中取出所有的blocks,调用pushBlocks方法



private def pushBlock(block: Block) {
  listener.onPushBlock(block.id, block.buffer)
  logInfo("Pushed block " + block.id)
}



ReceiverSupervisorImpl,它本生是一个接口,这是在standalone模式下的具体实现。所以说它是数据流中的Controller。

  在改监听器中定义了onPushBlock方法



def onPushBlock(blockId: StreamBlockId, arrayBuffer: ArrayBuffer[_]) {
    pushArrayBuffer(arrayBuffer, None, Some(blockId))
  }



  所以最终会调用其中的pushArrayBuffer方法。将数据放入到blocksForPushing队列中。

blocksForPushing的数据是由blockIntervalTimer定时器定期的将BlockGenerator的currentBuffer中的数据写入的。



private def updateCurrentBuffer(time: Long): Unit = {
  try {
    var newBlock: Block = null
    synchronized {
      if (currentBuffer.nonEmpty) {
        val newBlockBuffer = currentBuffer
        currentBuffer = new ArrayBuffer[Any]
        val blockId = StreamBlockId(receiverId, time - blockIntervalMs)
        listener.onGenerateBlock(blockId)
        newBlock = new Block(blockId, newBlockBuffer)
      }
    }
 
    if (newBlock != null) {
      blocksForPushing.put(newBlock)  // put is blocking when queue is full
    }
  } catch {
    case ie: InterruptedException =>
      logInfo("Block updating timer thread was interrupted")
    case e: Exception =>
      reportError("Error in block updating thread", e)
  }
}



每个200ms就会将currentBuffer中的数据写到blocksForPushing队列中,而blocksForPushing队列会每个10ms就写入到BlockManager中。

   最后借用一下兄弟们画的流程图

Core练习 Spark spark creativity_数据

 

 

Core练习 Spark spark creativity_Core练习 Spark_02