如何停止你的Streaming Application

weixin_33936401發表於2019-01-09
13394159-76118c8b472b9e07

 Spark 1.3及其前的版本

  你的一個 spark streaming application 已經好好執行了一段時間了,這個時候你因為某種原因要停止它。你應該怎麼做?直接暴力 kill 該 application 嗎?這可能會導致資料丟失,因為 receivers 可能已經接受到了資料,但該資料還未被處理,當你強行停止該 application,driver 就沒辦法處理這些本該處理的資料。

  所以,我們應該使用一種避免資料丟失的方式,官方建議呼叫StreamingContext#stop(stopSparkContext: Boolean, stopGracefully: Boolean),將 stopGracefully 設定為 true,這樣可以保證在 driver 結束前處理完所有已經接受的資料。

  一個 streaming application 往往是長時間執行的,所以存在兩個問題:

  應該在什麼時候去呼叫StreamingContext#stop

  當 streaming application 已經在執行了該怎麼去呼叫StreamingContext#stophow

  通過Runtime.getRuntime().addShutdownHook註冊關閉鉤子, JVM將在關閉之前執行關閉鉤子中的run函式(不管是正常退出還是異常退出都會呼叫),所以我們可以在 driver 程式碼中加入以下程式碼:

  Runtime.getRuntime().addShutdownHook(new Thread() {

  override def run() { log(Shutting down streaming app...)

  streamingContext.stop(true, true) log(Shutdown of streaming app complete.)

  }

  })

  這樣就能保證即使 application 被強行 kill 掉,在 driver 結束前,streamingContext.stop(true, true)也會被呼叫,從而保證已接收的資料都會被處理。

  Spark 1.4及其後的版本

  上一小節介紹的方法僅適用於 1.3及以前的版本,在 1.4及其後的版本中不僅不能保證生效,甚至會引起死鎖等執行緒問題。在 1.4及其後的版本中,我們只需設定spark.streaming.stopGracefullyOnShutdown為true即可達到上一小節相同的效果。

  下面來分析為什麼上一小節介紹的方法在 1.4其後的版本中不能用。首先,需要明確的是:

  當我們註冊了多個關閉鉤子時,JVM開始啟用其關閉序列時,它會以某種未指定的順序啟動所有已註冊的關閉鉤子,並讓它們同時執行

  萬一不止一個關閉鉤子,它們將並行地執行,並容易引發執行緒問題,例如死鎖綜合以上兩點,我們可以明確,如果除了我們註冊的關閉鉤子外,driver 還有註冊了其他鉤子,將會引發上述兩個問題。

  在 StreamingContext#start 中,會呼叫

  ShutdownHookManager.addShutdownHook(StreamingContext.SHUTDOWN_HOOK_PRIORITY)(stopOnShutdown)

  該函式最終註冊一個關閉鉤子,並會在run方法中呼叫stopOnShutdown,

  private def stopOnShutdown(): Unit = {

  val stopGracefully = conf.getBoolean(spark.streaming.stopGracefullyOnShutdown, false)

  logInfo(sInvoking stop(stopGracefully=$stopGracefully) from shutdown hook) // Do not stop SparkContext, let its own shutdown hook stop it

  stop(stopSparkContext = false, stopGracefully = stopGracefully)

  }

  從stopOnShutdown中會根據stopGracefully的值來決定是否以優雅的方式結束driver,而 stopGracefully的值由spark.streaming.stopGracefullyOnShutdown決定。結合上文,也就能說明為什麼spark.streaming.stopGracefullyOnShutdown能決定是否優雅的結束 application 和為什麼上一小節的方法不適用與 1.4及其後版本。

相關文章