Spark 的监控和性能调优高度依赖其内置的 Spark Web UI 和 Spark History Server。它们是诊断作业性能瓶颈、资源利用率、错误原因和优化机会的最重要工具。
一、Spark Web UI (Driver Web UI)
当一个 Spark 应用程序 (SparkContext
) 运行时,Driver 进程会启动一个 Web 服务器,默认端口是 4040
(如果 4040 被占用,则尝试 4041, 4042 等)。这是实时监控应用运行状态的核心界面。主要包含以下关键标签页 (Tabs):
-
Jobs Tab (作业标签页)
- 作用: 展示所有已完成的、正在运行的、以及失败的 Job 列表。
- 关键信息:
- Job ID: 作业的唯一标识。
- Description: 触发该 Job 的 Action (如
count()
,saveAs...
,collect()
,show()
,foreach()
等) 的描述,通常包含代码位置信息。 - Status: 完成、运行中、失败。
- Stages: 该 Job 包含的 Stage 数量 (已完成/总数)。
- Tasks (Total): 该 Job 所有 Stage 的 Task 总数。
- Duration: Job 的运行总时间。
- Stages Progress / Tasks Progress: 进度条直观显示。
- Event Timeline: 以时间线形式展示 Executor 添加/移除、Job/Stage 开始结束事件。
- 用途: 快速定位哪个 Action 触发的 Job 执行时间长或失败了;了解整体作业进度。
-
Stages Tab (阶段标签页)
- 作用: 展示所有 Stage 的状态。Stage 是 Spark 执行计划的基本调度单位,由一组可以并行计算的 Task 组成。Stage 的划分通常由 Shuffle 操作 (如
reduceByKey
,join
,groupByKey
) 决定。 - 关键信息 (Stage 列表):
- Stage ID: 阶段的唯一标识。
- Description: Stage 对应的操作描述 (通常是最后一个 RDD 转换操作)。
- Submitted: Stage 提交时间。
- Duration: Stage 运行时间。
- Tasks: Task 总数及完成比例。
- Input / Output / Shuffle Read / Shuffle Write: 极其重要! 数据量大小。
- Scheduler Delay: 极其重要! Task 在调度队列中等待的时间。高值通常表示集群资源不足或调度器繁忙。
- 关键信息 (进入单个 Stage 详情页):
- DAG Visualization (DAG 可视化): 图形化展示该 Stage 的计算逻辑 (RDD 转换链)。
- Summary Metrics (摘要指标):
- Task 耗时分布 (Min, 25th percentile, Median, 75th percentile, Max): 极其重要! 判断是否存在数据倾斜 (Data Skew)。如果 Max 远高于 Median/75th percentile,说明某些 Task 处理的数据量远大于其他 Task。
- Shuffle Read Size / Records: 从上游 Stage 读取的 Shuffle 数据量。关注是否过大。
- Shuffle Write Size / Records: 写入给下游 Stage 的 Shuffle 数据量。关注是否过大。
- GC Time: 极其重要! 所有 Task 垃圾回收 (Garbage Collection) 花费的总时间。高 GC Time (例如超过 Task 执行时间的 10-20%) 表明内存压力大,可能需要优化内存配置 (如增大 Executor 内存
spark.executor.memory
,调整内存比例spark.memory.fraction
/spark.memory.storageFraction
),或优化代码减少对象创建。 - Scheduler Delay: 同上。
- Peak Execution Memory: Task 使用的执行内存峰值。
- Task List (任务列表):
- 查看每个 Task 的详细信息:在哪个 Executor 上运行、耗时、GC 时间、Shuffle Read/Write 量、输入数据量、所在主机等。
- 用于定位慢 Task (Stragglers) 的具体位置和原因。
- 用途: 性能分析的核心页面。识别数据倾斜、Shuffle 瓶颈、GC 问题、调度延迟、慢 Task 等。
- 作用: 展示所有 Stage 的状态。Stage 是 Spark 执行计划的基本调度单位,由一组可以并行计算的 Task 组成。Stage 的划分通常由 Shuffle 操作 (如
-
Storage Tab (存储标签页)
- 作用: 展示被
persist()
或cache()
的 RDDs 和 DataFrames/Datasets 的信息。 - 关键信息:
- RDD Name / Dataset Name: 持久化数据集名称。
- Storage Level: 存储级别 (MEMORY_ONLY, MEMORY_AND_DISK, DISK_ONLY 等)。
- Cached Partitions: 已缓存的 Partition 数量 / 总 Partition 数量。
- Fraction Cached: 缓存比例。
- Size in Memory / Size on Disk: 在内存和磁盘上的大小。
- 用途: 检查缓存是否生效、缓存的数据量是否合理、是否因内存不足导致缓存频繁失效 (spilling to disk 或 recomputation)。
- 作用: 展示被
-
Executors Tab (执行器标签页)
- 作用: 展示所有当前活跃的和已完成的 Executor 的详细信息。Executor 是在 Worker 节点上运行 Task 的 JVM 进程。
- 关键信息 (Executor 列表):
- Executor ID / Address: 标识和位置。
- RDD Blocks / Storage Memory: 当前存储的 RDD Block 数和占用的存储内存。
- Tasks: 该 Executor 完成/失败/当前运行的 Task 数量。
- Shuffle Read / Write: 该 Executor 进行的 Shuffle 读写总量。
- Logs: 查看该 Executor 的日志 (排查错误的关键!)。
- Thread Dump: 获取 Executor JVM 的线程快照 (分析死锁、卡顿)。
- 资源使用 (核心指标图):
- GC Time: 极其重要! 该 Executor JVM 累积的 GC 时间。高值表明该 Executor 内存压力大。
- Input / Shuffle Read / Shuffle Write: 速率图。
- Task Time: Executor 执行 Task 累积耗时。
- Scheduler Delay: Executor 上 Task 累积的调度延迟。
- Peak Execution Memory: 该 Executor 上 Task 使用的执行内存峰值。
- 用途: 监控 Executor 资源使用情况 (特别是 GC)、识别有问题的 Executor (如持续高 GC、Shuffle 失败)、查看日志定位错误。
-
SQL/DataFrame Tab (SQL 标签页)
- 作用: 当应用程序使用 Spark SQL、DataFrame 或 Dataset API 时,此标签页提供额外的、更高级别的监控信息。
- 关键信息:
- Jobs: 关联的 SQL 查询触发的 Job。
- SQL Queries: 列出所有执行过的 SQL 查询或 DataFrame/Dataset 操作。
- Query Description: SQL 语句或操作描述。
- Duration: 查询总耗时。
- Job IDs: 该查询触发的 Job ID 列表。
- Details: 点击进入查询详情页,包含:
- DAG Visualization (Query Plan): 极其重要! 图形化展示物理执行计划 (Physical Plan)。可以看到数据源、Filter、Projection、Exchange (Shuffle)、Sort、HashAggregate 等操作符。是理解查询执行逻辑和性能瓶颈的关键。
- Metrics per Operator: 每个执行操作符的详细指标 (处理行数/字节数、耗时等),帮助定位计划中哪个步骤最耗时。
- Metrics Distribution: Task 级别的指标分布图,可检测数据倾斜。
- DataFrame Operations: 类似 SQL Queries,但针对 DataFrame/Dataset 的转换操作。
- 用途: 深入分析 Spark SQL 查询性能,理解执行计划,定位优化点 (如谓词下推、Join 策略选择、Shuffle 优化)。
-
Streaming Tab (流处理标签页 - 仅 Streaming 应用)
- 作用: 专用于监控 Structured Streaming 应用。
- 关键信息:
- Active Batches: 当前活跃的批处理。
- Completed Batches: 已完成的批处理列表。
- Batch ID / Duration / Input Rate / Processing Rate: 批处理标识、耗时、输入速率、处理速率。
- Scheduling Delay: 批处理在调度队列中的等待时间。
- Processing Time: 批处理实际执行时间。
- Aggregated Statistics: 关键指标 (输入速率、处理速率、调度延迟、处理时间) 的聚合统计和趋势图。
- Input / Output / State Operators: 流处理中特定操作符的统计信息。
- 用途: 监控流处理应用的吞吐量、延迟、稳定性。判断是否处理速度能跟上输入速度 (
Processing Rate
>=Input Rate
?),识别调度或处理瓶颈 (Scheduling Delay
/Processing Time
是否过高?)。
二、Spark History Server
- 作用: Spark Web UI 仅在应用程序运行时可用。一旦应用程序结束 (无论成功或失败),其 Web UI 也随之消失。Spark History Server 是一个独立的 Web 服务,它持久化存储已完成应用程序的事件日志 (
SparkEventLog
),并提供与运行时 Web UI 功能相同的历史界面。 - 配置启用:
- 在
spark-defaults.conf
中配置:spark.eventLog.enabled true
(启用事件日志记录)spark.eventLog.dir
(指定事件日志存储目录,如hdfs://namenode:8020/spark-logs
或file:///path/to/logs
- 生产环境强烈建议使用 HDFS/S3 等可靠存储)spark.history.fs.logDirectory
(History Server 读取日志的目录,通常与spark.eventLog.dir
相同)
- 启动 History Server 服务:
$SPARK_HOME/sbin/start-history-server.sh
- 在
- 访问: 默认端口
18080
。访问方式:http://<history-server-host>:18080
- 关键价值:
- 故障诊断: 在应用失败后,查看其完整的 Web UI 信息 (Jobs, Stages, Executors 日志等),分析失败原因。
- 性能分析: 在应用运行结束后,回顾其性能指标 (GC, Shuffle, Task 分布, Scheduler Delay),进行离线性能调优。
- 历史对比: 对比不同时间点、不同配置或不同代码版本下同一个应用的运行情况,评估优化效果。
- 审计: 查看历史作业的运行记录和资源消耗。
总结:关键指标与诊断思路
-
高 GC Time (Jobs/Stages/Executors Tab):
- 现象: GC Time 占 Task 时间或 Executor 时间的比例过高 (如 > 10-20%)。
- 可能原因: Executor 内存不足;创建过多临时对象;缓存数据过多挤占执行内存。
- 排查/优化: 增大
spark.executor.memory
;调整spark.memory.fraction
/spark.memory.storageFraction
;优化代码 (避免在 UDF 中创建大对象,复用对象,使用基本类型数组);减少缓存级别或缓存量;检查是否有内存泄漏。
-
大 Shuffle Read/Write (Stages/SQL/Executors Tab):
- 现象: Shuffle Read/Write 数据量非常大 (GBs 甚至 TBs)。
- 可能原因: 数据倾斜;不必要的 Shuffle (如
groupBy().count()
vscountByKey()
);Join 键分布不均;Shuffle 分区数不合理。 - 排查/优化: 在 Stages Tab 查看 Task 耗时分布判断倾斜;在 SQL Tab 查看物理计划定位产生大 Shuffle 的操作;使用
repartition
/coalesce
调整分区数;尝试 Broadcast Join 替代 Shuffle Join;对倾斜 Key 进行特殊处理 (如加盐 Salting);优化聚合逻辑。
-
数据倾斜 (Stages Tab - Task Time Distribution):
- 现象: 某个 Stage 的 Task 耗时 Max 远高于 Median/75th percentile (如 Max 是 Median 的 10 倍以上)。
- 可能原因: 输入文件大小不均;
groupByKey
,reduceByKey
,join
等操作的 Key 分布极度不均 (少数 Key 对应大量数据)。 - 排查/优化: 确认倾斜的 Stage 和操作;分析 Key 分布;尝试前述处理大 Shuffle 的方法 (特别是 Salting);增大 Shuffle 分区数 (
spark.sql.shuffle.partitions
) 有时能缓解;检查输入数据源是否本身有倾斜。
-
高 Scheduler Delay (Stages/Executors Tab):
- 现象: Scheduler Delay 较高 (尤其相对于 Task 执行时间)。
- 可能原因: 集群资源不足 (Executor 少,Core 少);Task 数量过多导致调度队列长;Driver 负载过高或网络延迟;资源管理器 (YARN/Mesos/K8s) 自身调度延迟。
- 排查/优化: 增加 Executor 数量 (
spark.executor.instances
) 或每个 Executor 的 Core 数 (spark.executor.cores
);调整spark.task.cpus
;优化 Task 大小/数量 (避免过多小 Task);检查 Driver 资源是否充足;检查集群资源管理器状态。
-
Streaming 延迟/积压 (Streaming Tab):
- 现象:
Processing Rate
<Input Rate
;Scheduling Delay
或Processing Time
持续增长;Batch Duration 远超设定值。 - 可能原因: 批处理计算逻辑太慢 (可能包含上述 GC/Shuffle/倾斜问题);资源不足;Kafka 等源分区数少,限制了并行度;Sink 写入慢。
- 排查/优化: 首先用 Jobs/Stages Tab 分析批处理作业的性能瓶颈 (按上述 1-4 点);增加资源;增加源分区数或调整
maxOffsetsPerTrigger
;优化 Sink 写入 (如批量写);考虑微批处理间隔 (trigger
)。
- 现象:
熟练掌握 Spark Web UI 和 History Server 是进行高效 Spark 应用开发、性能调优和故障排查的必备技能。 务必花时间熟悉各个标签页提供的信息及其关联关系,并重点关注 GC 时间、Shuffle 量、Task 时间分布和 Scheduler Delay 这些核心指标。