• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
Pzwxy
博客园    首页    新随笔    联系   管理    订阅  订阅

Spark版本定制第10天:流数据生命周期和思考

本期内容:

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)
}

  在pushBlocks方法又一个监听器,它属于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中。

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

 

 

备注:

资料来源于:DT_大数据梦工厂(Spark发行版本定制)

更多私密内容,请关注微信公众号:DT_Spark

如果您对大数据Spark感兴趣,可以免费听由王家林老师每天晚上20:00开设的Spark永久免费公开课,地址YY房间号:68917580

 

posted @ 2016-05-22 13:29  Pzwxy  阅读(295)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3