在分布式实时数据处理任务运行中,需要更新相关业务逻辑时,如何优雅的停止对应任务进程?
写个脚本将kill发送到对应任务运行节点上?这太暴力了,容易导致数据丢失问题。
在此通过监控hdfs的某个目录是否存在作为判断任务停止的依据,在需要停止时创建hdfs对应目录即可。为了下一次启动能够正常运行下去,关闭的时候还需要将对应hdfs目录删除。另外需要注意关闭标识路径需要一定的目录深度即标识度,避免与其他目录相冲突。
代码如下:
import java.net.URI
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.{FileSystem, Path}
import org.apache.spark.streaming.{StreamingContext, StreamingContextState}
class MonitorForGracefulStop(ssc: StreamingContext) extends Runnable {
override def run(): Unit = {
val fs: FileSystem = FileSystem.get(new URI("hdfs://chdp11:9000"), new Configuration(), "root")
while (true) {
try{
//most case using 20 seconds rough, this just for test
Thread.sleep(5000)
}
catch {
case e: InterruptedException =>
e.printStackTrace()
}
val state: StreamingContextState = ssc.getState
val bool: Boolean = fs.exists(new Path("/spark/monitor/streaming/stopStreaming"))
if (bool) {
if (state == StreamingContextState.ACTIVE) {
ssc.stop(stopSparkContext = true, stopGracefully = true)
println("stop gracefull by MonitorForGracefullStop!")
//delete tag directory for next start
fs.delete(new Path( "/spark/monitor/streaming/stopStreaming"),true)
System.exit(0)
}
}
}
}
}
使用时注意需要添加如下配置(注意代码位置)
ssc.start()
//invoke stop graceful thread
new MonitorForGracefulStop(ssc).run()
ssc.awaitTermination()
Spark会在JVM关闭时正常关闭StreamingContext,而不是立马关闭。
或者使用以下方法:
Kill 命令:yarn application -kill 后面跟 applicationid