返回

利用 Arthas 排查 Standby NameNode 加载 EditLog 慢的问题

开发工具

引言

在分布式存储系统中,NameNode 负责管理文件系统元数据,而 Standby NameNode 则作为其备份,时刻保持与 NameNode 的元数据同步。当 NameNode 发生故障时,Standby NameNode 可以快速接管,确保服务的连续性。然而,在实际运维中,我们遇到这样一个问题:Standby NameNode 加载 EditLog 的过程非常缓慢,严重影响了其接管速度。

问题定位

为了解决这个问题,我们首先需要定位问题所在。通过分析 Standby NameNode 的日志,我们发现问题出在第 2 步:从 JournalNode 拉取 EditLog 的过程中出现了固定的 15 秒延迟。

原因分析

一般来说,空集群几乎没有操作,EditLog 也不会太大,因此不应该每次从 JournalNode 拉取 EditLog 都耗费 15 秒的时间。进一步分析日志后,我们发现以下关键信息:

2023-03-08 10:35:15,807 INFO  org.apache.hadoop.hdfs.server.namenode.EditLogFileOutputStream: Sync on file 0x43e361c88 took 15508ms

这表明在将 EditLog 写入本地文件系统时出现了同步操作,导致了 15 秒的延迟。

解决方案

根据上述分析,我们知道问题在于 EditLog 写入本地文件系统时的同步操作。为了解决这个问题,我们可以使用 Arthas 工具动态修改正在运行的 Java 程序的行为,从而禁用同步操作。

具体来说,我们可以使用 Arthas 的 watch 命令来观察 EditLogFileOutputStream 类的 sync 方法,并使用 edit 命令来修改该方法的实现,使其不执行同步操作。

# 使用 watch 命令观察 EditLogFileOutputStream 类的 sync 方法
watch org.apache.hadoop.hdfs.server.namenode.EditLogFileOutputStream sync

# 使用 edit 命令修改 sync 方法的实现
edit org.apache.hadoop.hdfs.server.namenode.EditLogFileOutputStream sync doNothing()

效果验证

修改代码后,我们重新启动了 Standby NameNode,并观察到了以下效果:

2023-03-08 10:45:15,807 INFO  org.apache.hadoop.hdfs.server.namenode.EditLogFileOutputStream: Sync on file 0x43e361c88 took 0ms

可以看到,EditLog 写入本地文件系统时的同步操作已经禁用,加载 EditLog 的过程也不再出现固定 15 秒的延迟。

总结

通过使用 Arthas 工具,我们成功地定位并解决了 Standby NameNode 加载 EditLog 慢的问题。该解决方案不仅有效地提升了 Standby NameNode 的接管速度,也为我们提供了排查分布式系统性能问题的新思路。