Spark streaming应用状态监控及其自动重启脚本

本文介绍了一种在没有提供高级工具的大数据环境中,使用Shell脚本自动化监控和重启Spark应用的方法。脚本每10分钟检查应用状态,如未运行则重启,且每日凌晨强制重启,以确保应用稳定运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spark 应用的状态监控,应用提交,应用定时重启等等,有很多开源的组件可以用的方案,比如说hue,azkaban,oozie之类的。总有一些客户提供大数据环境,不提供一些工具,嫌弃工具的。那只能通过最原始的方法来提交Spark应用,应用状态监控只能通过脚本来实现。

脚本主要内容每隔10分钟检查一次状态,如果不在运行,则重启。由于客户自己要求还加了一个凌晨无论在不在运行,都是先关闭,然后在重启。唉。。。。。写脚本也是无奈之举,总有人生活在原始社会。脚本如下:

#!/bin/bash
# check spark app state
# if not running, restart spark app
#
# */10 * * * * /opt/spark/autorestart-sparkapp.sh 2>&1
#
basePath=$(pwd)
proxyUser="用户名,提交程序的应用名,免得把别人的程序kill掉了"
# 下面规定多几个匹配条件,就是匹配误杀的。
applicationType="SPARK"
appStatus="RUNNING"
# 日志临时目录
logDir=/tmp/aaaaaaaalog
initLockFile=${basePath}/autoInitSparkApp.lock
isNeedInit=false
nowDate=$(date "+%Y%m%d")
nowTime=$(date "+%H%M")

# wait app seconds
maxStartAppWait=600

if [ ! -e ${initLockFile} ]&&[[ ${nowTime} < "0200" ]]; then
  isNeedInit=true
elif [ -e ${initLockFile} ];then
  initDate=$(cat ${initLockFile})
  if [ X${initDate} != X${nowDate} ]&&[[ ${nowTime} < "0200" ]]; then
      isNeedInit=true
  fi
fi

if [ ! -d "$logDir" ] ; then
  mkdir $logDir
fi
# 用于临时存储spark 应用列表
jobListFile=/tmp/aaalog/jobList.txt
# aaaaaa之类代表应用名称,匹配误杀,多个判断条件安全一点
allAppNames=("aaaaaa" "bbbbbb" "cccccc")

yarn application -list 2>/dev/null|awk '{print $0;}'|grep -E "aaaaaa|bbbbbb|cccccc" > ${jobListFile}


declare isRunning=false

for idx in $(seq 0 ${#allAppNames[@]}) ;
do
  appName=${allAppNames[$idx]}
  isRunning=false;
  jobId=""
  if [ -z $appName ];then
    continue;
  fi
  while read line
  do
    jobId=$(echo $line|awk '{print $1;}');
    jobName=$(echo $line|awk '{print $2;}');
    appType=$(echo $line|awk '{print $3;}');
    user=$(echo $line|awk '{print $4;}');
    queue=$(echo $line|awk '{print $5;}');
    jobStatus=$(echo $line|awk '{print $6;}');
    if [ ! -z $appName ]&&[ "$appName" == "$jobName" ]&&[ "$proxyUser" = "$user" ]&&[ "$appType" = "$applicationType" ]&&[ "$appStatus" = "$jobStatus" ];then
       isRunning=true
       break;
    elif [ ! -z $appName ]&&[ "$appName" == "$jobName" ]&&[ "$proxyUser" = "$user" ]&&[ "$appType" = "$applicationType" ];then
       isRunning=false     
       break;
    else
       jobId=""
       jobName=""
       jobStatus=""
       isRunning=false
    fi
  done < $jobListFile

  if [ $isRunning = true ];then
    echo "Spark application "$appName" is running!"
    if [ ${isNeedInit} = true ]&&[ ! -z $jobId ];then
       yarn application -kill $jobId
    fi
    jobId=""
  else
    finishTime=0;
    timeDiff=0;
    if [ ! -z $jobId ];then
       finishTime=`yarn application -status $jobId 2>/dev/null | grep "Finish-Time" | awk '{print $NF}'`
       if [ "$finishTime" -eq 0 ]; then
         timeDiffExpr=`date +%s`-`yarn application -status $jobId 2>/dev/null | grep "Start-Time" | awk '{print $NF}' | sed 's!$!/1000!'`
         timeDiff=`echo $timeDiffExpr|bc`
         # wait for $maxStartAppWait time maybe allays accept status
         if [ "$timeDiff" -gt "$maxStartAppWait" ];then
            yarn application -kill $jobId
	    sleep 15s
	 else
	    continue;
         fi
       fi
    fi     

    if [ x"$appName" == x"${allAppNames[0]}" ];then
       echo "Spark Submit $appName to Cluster!!"
       # aaaaa 的应用提交脚本
       nohup sh $basePath/run-aaaaaa-cluster.sh  2>&1 >/dev/null &
    elif [ x"$appName" == x"${allAppNames[1]}" ];then
       echo "Spark Submit $appName to Cluster!!"
       #  bbbbbb的应用提交脚本
       nohup sh $basePath/run-bbbbbb-cluster.sh 2>&1 >/dev/null &
    elif [ x"$appName" == x"${allAppNames[2]}" ];then
       echo "Spark Submit $appName to Cluster!!"
       #  cccccc的应用提交脚本
       nohup sh $basePath/run-cccccc-cluster.sh 2>&1 >/dev/null &
    fi
    sleep 30s
  fi
done

if [ ${isNeedInit} = true ]; then
  # delete checkpoint directory
  hadoop fs -rm -r -f /tmp/aaaaaa/checkpoint
  hadoop fs -rm -r -f /tmp/bbbbbb/checkpoint
  echo ${nowDate} > ${initLockFile}
fi

 

<think>好的,我现在需要解决用户提出的关于Spark应用程序进程被意外终止的问题。用户提到他们希望了解如何处理这类问题以及相应的解决方案。首先,我需要回顾一下用户提供的引用内容,看看是否有相关的信息可以帮助我构建答案。 根据引用[2],用户提到在YARN集群中,手动逐个终止应用效率低下,特别是当有大量需要终止的应用时。这可能涉及到YARN的资源管理和应用管理机制。引用[3]提到了CoarseGrainedExecutorBackend进程和Executor ID,这可能与Spark的Executor进程相关,而引用[4]则涉及NodeManager的本地目录管理,可能与依赖包下载有关。 接下来,我需要结合自己的知识,分析Spark应用被kill的可能原因。通常,进程被终止可能包括资源不足、配置错误、人为操作(如手动kill)、任务超时或失败等。解决方案可能涉及资源调整、配置优化、监控告警机制以及批处理脚本的使用。 用户提供的引用[2]中提到YARN没有提供批量终止应用的命令,因此可能需要编写脚本自动化这一过程。例如,使用Shell脚本结合YARN的命令来批量获取应用ID并执行kill操作。这可能是一个有效的解决方案,需要详细说明如何实现。 另外,引用[3]和[4]可能提示了需要检查Executor的资源使用情况,或者依赖包是否正确下载,以避免任务失败导致的进程终止。例如,配置资源参数如executor内存、cores,或者调整动态分配策略,以防止资源不足引发的失败。 在整理解决方案时,需要分步骤说明原因分析和对应的解决方法。例如,先分析资源不足的问题,然后给出调整资源配置的建议;接着讨论人为误操作,提出权限管理和监控告警的方法;最后,针对批量kill的需求,提供脚本示例。 还需要考虑如何预防进程被kill,例如设置资源预留、合理调度任务、加强监控等。同时,引用[2]中的批处理kill方法需要详细说明如何编写脚本,引用YARN的REST API或命令行工具。 最后,生成相关问题时要围绕Spark应用管理、资源优化、监控工具和批量操作等方面展开,确保问题具有相关性和实用性。</think>### Spark应用程序进程被终止的解决方案 #### 一、原因分析 1. **资源不足** - 集群资源(CPU、内存)超额分配,触发YARN的资源管理机制强制终止进程[^2][^3]。 - 示例:若Executor内存超限,YARN的`NodeManager`会直接终止对应容器。 2. **人为误操作** - 管理员手动执行`yarn application -kill <appId>`导致进程终止[^2]。 3. **任务失败或超时** - 应用逻辑错误、依赖缺失(如Jar包未正确下载到`nm-local-dir`)[^4]。 - 心跳超时(如网络问题导致`ApplicationMaster`与ResourceManager通信中断)。 --- #### 二、解决方案 ##### 1. 资源优化配置 - **调整Executor资源参数** 在`spark-submit`中明确指定资源需求: ```bash --executor-memory 8g \ --executor-cores 4 \ --conf spark.yarn.executor.memoryOverhead=1024 ``` - 避免内存超限,`memoryOverhead`需覆盖堆外内存需求。 - **启用动态资源分配** 添加配置以允许Spark自动释放闲置Executor: ```properties spark.dynamicAllocation.enabled=true spark.shuffle.service.enabled=true ``` ##### 2. 防止人为误杀 - **权限管控** 通过YARN的队列ACL限制操作权限: ```xml <property> <name>yarn.acl.enable</name> <value>true</value> </property> <property> <name>yarn.admin.acl</name> <value>admin_user</value> </property> ``` - **监控告警集成** 使用Prometheus+Grafana监控应用状态,触发异常时通知责任人。 ##### 3. 进程终止后的恢复机制 - **Checkpoint持久化** 对Spark Streaming或结构化流处理应用启用Checkpoint: ```scala val query = df.writeStream .format("parquet") .option("checkpointLocation", "/path/to/checkpoint") .start() ``` - **任务重试策略** 配置`spark.yarn.maxAppAttempts`控制最大重试次数: ```bash --conf spark.yarn.maxAppAttempts=3 ``` ##### 4. 批量终止进程(针对误操作场景) - **Shell脚本批量处理** 通过YARN API获取`RUNNING`状态应用列表并终止: ```bash # 获取所有RUNNING状态应用ID app_ids=$(yarn application -list | awk '$6 == "RUNNING" {print $1}') # 批量终止 for app_id in $app_ids; do yarn application -kill $app_id done ``` - 支持正则匹配特定用户或队列的应用[^2]。 --- #### 三、预防措施 1. **资源预留策略** 在YARN中为关键应用分配专用队列,设置最小资源保障: ```xml <queue name="critical"> <minResources>8000 mb, 4 vcores</minResources> </queue> ``` 2. **依赖包预分发** 将Spark应用依赖的Jar包预上传至HDFS路径,避免运行时下载失败[^4]: ```bash hdfs dfs -put lib/*.jar /user/spark/libs/ ``` 3. **健康检查机制** 在Driver中定期上报心跳至外部系统(如ZooKeeper),超时则自动重启。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值