优雅的停止SparkStreaming

本文介绍了一种在Spark Streaming中实现流式任务7*24小时运行时,如何通过外部文件控制优雅关闭的方法。通过在HDFS上创建特定文件,程序能够响应并优雅地停止,避免了直接杀掉进程带来的数据丢失风险。

背景:流式任务需要7*24小时执行,但是有时涉及到升级代码需要主动停止程序,但是分布式程序,没办法做到一个个进程去杀死,所有配置优雅的关闭就显得至关重要了。可以考虑使用外部文件存储或者关系型数据库、缓存等来控制内部程序关闭。

此例子使用hdfs创建指定文件来控制程序的关闭,想要更好的在前端进行控制,可以在注册程序中修改标志源。

package com.smothclose

import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.{FileSystem, Path}
import org.apache.spark.streaming.{StreamingContext, StreamingContextState}

class MonitorStop(ssc: StreamingContext) extends Runnable {

  override def run(): Unit = {

    val configuration = new Configuration()
    configuration.set("fs.defaultFS","hdfs://node01:8020")
    configuration.set("user","hadoop")
    val fs: FileSystem = FileSystem.get(configuration )

    while (true) {
      try
        Thread.sleep(5000)
      catch {
        case e: InterruptedException =>
          e.printStackTrace()
      }
      val state: StreamingContextState = ssc.getState

      val bool: Boolean = fs.exists(new Path("/stopSparkTest"))

      if (bool) {
        if (state == StreamingContextState.ACTIVE) {
          ssc.stop(stopSparkContext = true, stopGracefully = true)
          System.exit(0)
        }
      }
    }
  }
}
package com.smothclose

import org.apache.log4j.{Level, Logger}
import org.apache.spark.SparkConf
import org.apache.spark.streaming.dstream.{DStream, ReceiverInputDStream}
import org.apache.spark.streaming.{Seconds, StreamingContext}

object SparkTest {

  def createSSC(): _root_.org.apache.spark.streaming.StreamingContext = {
    val update: (Seq[Int], Option[Int]) => Some[Int] = (values: Seq[Int], status: Option[Int]) => {

      //当前批次内容的计算
      val sum: Int = values.sum

      //取出状态信息中上一次状态
      val lastStatu: Int = status.getOrElse(0)

      Some(sum + lastStatu)
    }

    val sparkConf: SparkConf = new SparkConf().setMaster("local[4]").setAppName("SparkTest")
    //	如果为true,Spark会StreamingContext在JVM关闭时正常关闭,而不是立即关闭。
    sparkConf.set("spark.streaming.stopGracefullyOnShutdown", "true")

    val ssc = new StreamingContext(sparkConf, Seconds(5))

    ssc.checkpoint("./ck1111")

    val line: ReceiverInputDStream[String] = ssc.socketTextStream("node01", 9999)

    val word: DStream[String] = line.flatMap(_.split(" "))

    val wordAndOne: DStream[(String, Int)] = word.map((_, 1))

    val wordAndCount: DStream[(String, Int)] = wordAndOne.updateStateByKey(update)

    wordAndCount.print()

    ssc
  }

  def main(args: Array[String]): Unit = {

    val ssc: StreamingContext = StreamingContext.getActiveOrCreate("./ck", () => createSSC())

    new Thread(new MonitorStop(ssc)).start()

    ssc.start()
    ssc.awaitTermination()
  }
}

会有一个常驻线程来监控标志位文件是否存在,若存在检查该ssc(StreamingContext)的状态是否为活跃,若是活跃状态进行停职该线程。

注:需要开启优雅关闭配置(默认是false)

### Spark Streaming优雅关闭实现方式 为了实现 Spark Streaming优雅关闭,可以利用 `spark.streaming.stopGracefullyOnShutdown` 配置项并结合特定的操作流程完成。以下是详细的说明: #### 1. 配置选项 通过设置配置项 `spark.streaming.stopGracefullyOnShutdown=true` 可以启用优雅关闭功能[^1]。此配置的作用是在应用程序接收到终止信号(如 SIGTERM)时,允许 Spark Streaming 应用程序在完全处理完当前批次后再退出。 #### 2. 发送终止信号 当需要停止 Spark Streaming 程序时,需向 Driver 进程发送 SIGTERM 信号。这可以通过操作系统命令或者自动化工具完成。一旦 Driver 收到该信号,它会启动优雅关闭过程[^2]。 #### 3. 关闭流程概述 在优雅关闭过程中,Driver 节点会等待所有正在运行的任务完成后才真正结束应用。这意味着不会丢失任何未处理的数据,并且能够确保所有的输入数据都被正确消费和存储[^4]。 #### 4. 示例代码 以下是一个简单的示例代码片段展示如何配置以及捕获外部中断信号来进行优雅关闭操作: ```scala import org.apache.spark.SparkConf import org.apache.spark.streaming.{Seconds, StreamingContext} object GracefulShutdownExample { def main(args: Array[String]): Unit = { val conf = new SparkConf().setAppName("Graceful Shutdown Example").setMaster("local[*]") .set("spark.streaming.stopGracefullyOnShutdown", "true") // 启动优雅关闭模式 val ssc = new StreamingContext(conf, Seconds(5)) try { // 定义 DStream 和其他逻辑... ssc.start() ssc.awaitTermination() // 此方法会在接收到SIGTERM后自动调用stop(true)进行优雅关闭 } catch { case e: Exception => println(s"Exception occurred: ${e.getMessage}") ssc.stop(stopSparkContext = true, stopGracefully = true) } } } ``` #### 5. 注意事项 尽管上述机制提供了基本保障,但在某些情况下仍需要注意额外因素: - 如果 Producer 数据生成速度远超设定的最大接收率 (`spark.streaming.receiver.maxRate`) ,即使启用了优雅关闭也可能因为积压过多而无法及时清理全部缓冲区中的消息[^3]。 - 对于高吞吐量场景下建议调整合适的 batch interval 来平衡延迟与性能之间的关系。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值