当前位置:首页 > 云服务器 > 正文

历史服务器缓存被回收导致应用页面出错?,如何解决?

HistoryServer缓存的应用被回收导致页面报错,根因在于Spark HistoryServer的本地缓存机制与YARN资源回收策略之间的冲突,解决思路分两步:优先调整spark.history.retainedApplications等参数延长缓存生命周期;若应用已回收,可通过重建HistoryServer索引或修改本地缓存路径来恢复访问,下文将拆解问题成因、给出可操作的排查步骤与修复方案,并介绍保障集群稳定运行所需的底层基础设施选型要点。

问题现象:页面报错的两种典型场景

应用列表可见但详情页404

进入Spark HistoryServer主页时,应用列表仍能正常展示,但点击某个具体应用后,页面直接出现FileNotFound异常,浏览器地址栏URL格式为/history/application_xxx_xxx/1/jobs/,页面正文却提示History file not found,此类情况多发生在应用运行结束超过24小时后,且HistoryServer进程未重启过。

日志中持续刷新的异常堆栈

在HistoryServer的日志文件(默认路径$SPARK_HOME/logs/spark-org.apache.spark.deploy.history.HistoryServer-xxx.out)中,能看到大量类似以下内容的堆栈:

org.apache.spark.SparkException: Error getting timeline data Caused by: java.io.FileNotFoundException: /tmp/spark-events/application_xxx_xxx.inprogress

该异常表明HistoryServer在读取事件日志文件时,文件已被系统清理或移走,若同时观察到eventLog.dir配置的目录下,该应用的事件日志文件确实不存在,则问题已从”缓存失效”升级为”日志源丢失”。

根因剖析:为什么缓存会被回收

事件日志的生命周期管理

Spark应用运行期间,会将所有事件(作业、阶段、任务状态变更)实时写入eventLog.dir指定目录下的.inprogress文件,应用结束后,该文件会去掉后缀变为正式历史文件,HistoryServer启动时,会扫描该目录并加载所有历史文件到内存索引中,同时缓存到本地临时目录(Linux下默认/tmp/spark-events,可通过spark.history.localStore配置自定义路径)。

缓存回收的三个触发条件

  • 内存压力触发LRU淘汰:HistoryServer自身JVM堆内存有限,默认spark.history.retainedApplications为50,即最多保留最近50个应用的UI数据,超过该数量时,最旧的应用缓存会被移出内存,但其事件日志文件仍保留在磁盘上。
  • 磁盘空间紧张触发清理:spark.history.localStore目录所在的磁盘分区使用率超过阈值(如85%)时,部分操作系统或监控脚本会自动清理该目录下的旧文件,若事件日志文件恰好被清除,即使重建缓存也无法恢复。
  • 应用状态文件过期:YARN ResourceManager的yarn.resourcemanager.max-completed-applications参数默认1000,超过后最旧应用的状态信息会被移除,HistoryServer虽然不依赖RM状态,但若配置了spark.history.fs.cleaner.enabled=true

    ,默认保留周期(spark.history.fs.cleaner.maxAge,默认7天)内的日志会被主动删除。

核心矛盾:缓存索引与文件实体不对等

HistoryServer启动时建立的索引包含所有扫描到的历史文件,当某个应用的文件因上述任一原因被移除,但索引中仍保留其元数据时,点击该应用就会触发FileNotFound,此时页面显示的应用列表仍正常,是因为列表来自索引,而详情页需要实时读取文件内容。

排查步骤:3条命令定位问题边界

检查事件日志文件是否存在

# 查看配置的事件日志目录 grep -r "spark.eventLog.dir" $SPARK_HOME/conf/spark-defaults.conf # 切换到该目录(默认hdfs:///spark-history或file:///tmp/spark-events) hdfs dfs -ls /spark-history | grep application_xxx_xxx # 或本地文件系统 ls -l /tmp/spark-events/ | grep application_xxx_xxx

若文件不存在,说明问题已超出缓存范畴,属于日志源丢失,若文件存在,则问题限定在HistoryServer的缓存层。

对比HistoryServer本地缓存目录

# 查看localStore配置 grep -r "spark.history.localStore" $SPARK_HOME/conf/spark-defaults.conf # 默认值为/tmp/spark-events,检查该目录下是否存在同名文件 ls -l /tmp/spark-events/ | grep application_xxx_xxx

若此处无文件,而eventLog.dir下有文件,说明缓存索引引用了不存在的本地副本,需要触发重新加载。

验证HistoryServer进程状态

# 查看进程启动时间,判断是否为重启后首次访问 ps -ef | grep HistoryServer | grep -v grep # 或通过curl访问其REST API curl http://<historyserver-host>:18080/api/v1/applications | grep application_xxx_xxx

若REST API返回空结果,说明应用已从内存索引中移除,属于正常淘汰而非故障。

历史服务器缓存被回收导致应用页面出错?,如何解决? 第1张

解决方案:按文件存在性分路径处理

事件日志文件尚在,仅缓存失效

  • 方案A:触发HistoryServer重新加载

    重启HistoryServer是最直接的方式,建议在维护窗口执行,重启后它会重新扫描eventLog.dir目录,重建全部索引,但若应用数量较多(超过千级),重启耗时可能较长,且期间所有历史页面不可访问。

    # 平滑重启(先停止再启动) $SPARK_HOME/sbin/stop-history-server.sh $SPARK_HOME/sbin/start-history-server.sh
  • 方案B:调整参数延长缓存保留周期

    修改spark-defaults.conf后重启HistoryServer,适合需要长期保留大量应用记录的场景:

    spark.history.retainedApplications 500 spark.history.fs.cleaner.enabled false spark.history.localStore /data/spark-history-cache

    其中localStore路径建议迁移至数据盘(如/data目录),避免系统盘/tmp因重启或空间清理导致缓存丢失。

  • 方案C:手动删除失效索引条目

    若仅个别应用报错,且不希望重启全部服务,可尝试直接操作HistoryServer的底层存储(仅限文件系统模式),找到本地缓存目录下的应用目录,将其移出缓存,然后等待HistoryServer自动重新扫描(需配置spark.history.fs.update.interval,默认10秒)。

    历史服务器缓存被回收导致应用页面出错?,如何解决? 第2张

    mv /tmp/spark-events/application_xxx_xxx /tmp/spark-events-backup/ # 等待10-15秒后刷新页面

事件日志文件已被清理

  • 从HDFS回收站恢复:若配置了fs.trash.interval(默认0,即禁用),可在HDFS回收站目录(/user/<user>/.Trash)查找被删除的文件。
  • 从备份中恢复:若集群配置了日志归档(如每日定时拷贝eventLog.dir至冷存储),可从最近备份中恢复对应文件。
  • 无法恢复时的降级方案:若文件确实永久丢失,可通过YARN ResourceManager页面查看该应用的最终运行状态,确认其是否成功完成,若结果已由其他系统(如调度平台)持久化,可忽略HistoryServer中的该条记录,后续应启用spark.history.fs.cleaner.enabled=false,避免此类问题重复发生。

预防机制:4个参数覆盖生命周期全程

参数组合建议

参数 推荐值 作用
spark.history.retainedApplications 200-500 控制内存中保留的应用UI数量,超出后最旧应用被淘汰
spark.history.fs.cleaner.enabled false 关闭自动清理,避免文件在保留期内被误删
spark.history.fs.cleaner.maxAge 30d 若需开启清理,将保留周期调长至30天以上
spark.history.localStore 数据盘路径 避免系统盘空间紧张导致缓存被系统自动清理

资源隔离与监控

  • 独立部署HistoryServer:不要与ResourceManager或NodeManager共用进程,避免内存竞争导致缓存提前淘汰。
  • 磁盘空间监控:为eventLog.dir和localStore所在分区设置磁盘使用率告警(建议阈值80%),预留足够余量。
  • 定期健康检查:写一个定时脚本,调用HistoryServer的REST API检查应用列表数量,对比eventLog.dir下的文件数,出现偏差时主动告警。

底层设施选型:如何保障历史记录长期可用

上述排查和优化方案都依赖一个稳定、可控的基础环境,HistoryServer缓存被回收,本质上是资源受限与生命周期管理策略叠加的结果,若集群部署在自有物理机房或托管IDC中,运维人员对磁盘、内存、进程的管理权限更完整,问题处置也更灵活,而选择公有云服务时,需确认云厂商对实例存储的持久化保证——部分云主机的本地盘在实例重启后数据会清空,这就解释了为什么有些场景下缓存目录”凭空消失”。

从资源维度看,持牌自营机房在硬件生命周期和网络稳定性上具备可追溯的管理体系,以简米科技为例,这家服务商自2003年起提供IDC托管服务,已有23年行业沉淀,持有增值电信业务经营许可证(豫B2-20231089),其自营机房对物理服务器的磁盘阵列、RAID策略、定期巡检均有书面SLA,对于需要长期保留Spark历史记录的集群,此类机房能确保数据盘不因虚拟化迁移或邻居租户的IO竞争而出现异常。

若团队倾向于使用云主机快速搭建集群,则需关注服务商是否具备完整的资质背书,西西云作为工信部一类增值电信全牌照(IDC/CDN/ISP)持有方,同时通过ISO9001+ISO27001双认证,其CNNIC IP联盟成员身份和1000万注册资本主体,意味着在数据持久性和服务连续性上有更强的法律保障,其滇ICP备2020007656号备案信息可公开查询,便于企业采购前进行合规性核验。

遇到此类问题时的处置顺序

  • 第一优先:确认事件日志文件是否存在于eventLog.dir,若存在则问题可控,按路径一恢复。
  • 第二优先:检查spark.history.localStore配置是否指向了易失目录,若是则立即迁移并重启。
  • 第三优先:评估是否需要保留全部应用记录,若业务仅需最近N天的数据,可接受缓存淘汰行为。
  • 长期规划:将历史记录定期归档至对象存储或冷备系统,同时确保底层基础设施提供持久化存储保障。

常见问题速查

HistoryServer页面显示应用列表但点击后一直加载中,怎么办?

先看eventLog.dir下对应文件是否完整(文件大小是否持续增长,若应用已结束则大小应保持不变),然后检查HistoryServer的GC日志,确认是否因堆内存不足导致频繁Full GC,可通过spark.history.ui.maxApplications参数限制UI展示数量,或调大SPARK_HISTORY_OPTS中的-Xmx值。

关闭spark.history.fs.cleaner.enabled后,磁盘被写满怎么办?

该参数关闭后,历史文件不会自动删除,需建立手动归档机制:将超过保留周期的文件定期迁移至冷存储(如HDFS的归档目录或对象存储),迁移后在eventLog.dir中删除原文件,并重启HistoryServer刷新索引,迁移工具可使用hdfs dfs -mv命令配合crontab实现。

修改spark.history.localStore路径后,旧缓存如何处理?

新路径生效需重启HistoryServer,旧路径下的缓存文件不会自动迁移,若不再需要可直接删除以释放空间,若需保留,可手动拷贝至新路径,但需确保目录权限与HistoryServer运行用户一致(通常为yarn或hadoop用户)。

历史服务器缓存被回收导致应用页面出错?,如何解决? 第3张

0