乐趣区

关于云原生-cloud-native:利用-Arthas-解决启动-StandbyNameNode-加载-EditLog-慢的问题

作者 | yhf20071

【Arthas 官网社区正在举办征文活动,加入即有奖品拿~ 点击投稿】

公司新搭 HDFS 集群,namenode 做 ha,然而在启动 StandbyNamenode 节点的时候呈现奇怪的景象:空集群加载 Editlog 很慢,每次重启简直耗时都在二三十分钟

为了不便大家了解,大抵说下 StandbyNamenode(以下简称 SNN)启动过程:

  • SNN 启动时,如果本地没有 FSImage 会去 ANN(ActiveNamenode)拉取 FSImage
  • 如果本地有 FSImage,则会依据 transactionId 去 JournalNode 拉取 gap 的 editlog,在本地做合并

问题就出在第 2 步,在从 JournalNode 拉取 EditLog 过程中呈现固定 15s 提早。一般来说,空集群简直没有操作,editlog 不会太大,不应该呈现每次从 JournalNode 拉取 EditLog 都消耗 15s 的工夫,日志如下(为了不便察看截取局部日志):

2020-11-04 18:27:27,577 INFO namenode.RedundantEditLogInputStream (RedundantEditLogInputStream.java:nextOp(177)) - Fast-forwarding stream 'http://cbdp-online1.sdns.fin ancial.cloud:8480/getJournal?jid=hdfs-ha&segmentTxId=213656&storageInfo=-64%3A272699407%3A1603893889358%3ACID-aa8ec1b5-a501-4195-9299-e14abefbdc11&inProgressOk=true' to transaction ID 184269 2020-11-04 18:27:42,582 INFO namenode.FSEditLogLoader (FSEditLogLoader.java:loadEditRecords(289)) - replaying edit log: 1/44 transactions completed. (2%) 2020-11-04 18:27:42,583 INFO namenode.FSImage (FSEditLogLoader.java:loadFSEdits(162)) - Edits file http://cbdp-online1.sdns.financial.cloud:8480/getJournal?jid=hdfs-ha &segmentTxId=213656&storageInfo=-64%3A272699407%3A1603893889358%3ACID-aa8ec1b5-a501-4195-9299-e14abefbdc11&inProgressOk=true, http://cbdp-online2.sdns.financial.cloud:8 480/getJournal?jid=hdfs-ha&segmentTxId=213656&storageInfo=-64%3A272699407%3A1603893889358%3ACID-aa8ec1b5-a501-4195-9299-e14abefbdc11&inProgressOk=true, http://cbdp-onli ne3.sdns.financial.cloud:8480/getJournal?jid=hdfs-ha&segmentTxId=213656&storageInfo=-64%3A272699407%3A1603893889358%3ACID-aa8ec1b5-a501-4195-9299-e14abefbdc11&inProgres sOk=true of size 5981 edits # 44 loaded in 15 seconds

......

2020-11-04 18:27:42,583 INFO namenode.RedundantEditLogInputStream (RedundantEditLogInputStream.java:nextOp(177)) - Fast-forwarding stream 'http://cbdp-online1.sdns.financial.cloud:8480/getJournal?jid=hdfs-ha&;segmentTxId=213700&storageInfo=-64%3A272699407%3A1603893889358%3ACID-aa8ec1b5-a501-4195-9299-e14abefbdc11&inProgressOk=true' to transaction ID 184269 2020-11-04 18:27:57,588 INFO namenode.FSEditLogLoader (FSEditLogLoader.java:loadEditRecords(289)) - replaying edit log: 1/53 transactions completed. (2%) 2020-11-04 18:27:57,589 INFO namenode.FSImage (FSEditLogLoader.java:loadFSEdits(162)) - Edits file http://cbdp-online1.sdns.financial.cloud:8480/getJournal?jid=hdfs-ha&;segmentTxId=213700&storageInfo=-64%3A272699407%3A1603893889358%3ACID-aa8ec1b5-a501-4195-9299-e14abefbdc11&inProgressOk=true, http://cbdp-online2.sdns.financial.cloud:8480/getJournal?jid=hdfs-ha&;segmentTxId=213700&storageInfo=-64%3A272699407%3A1603893889358%3ACID-aa8ec1b5-a501-4195-9299-e14abefbdc11&inProgressOk=true, http://cbdp-online3.sdns.financial.cloud:8480/getJournal?jid=hdfs-ha&;segmentTxId=213700&storageInfo=-64%3A272699407%3A1603893889358%3ACID-aa8ec1b5-a501-4195-9299-e14abefbdc11&inProgressOk=true of size 7088 edits # 53 loaded in 15 seconds

1. 首先通过日志初步定位代码,粗略定位耗时办法

trace org.apache.hadoop.hdfs.server.namenode.FSEditLogLoader loadFSEdits

2. 下面的后果只能确定大抵耗时办法块,不能精确定位理论耗时办法,如果要精确定位,须要一层一层开展,其中还波及回调函数、native 函数;为了能够更不便的定位代码,咱们先执行 profiler start,察看下耗时函数调用

profiler start/stop

3. 持续追踪函数

trace org.apache.hadoop.hdfs.server.namenode.EditLogFileInputStream$URLLog$1 run

4. 因为过程中波及了 jdk 函数追踪,咱们须要设置 options unsafe true

trace --skipJDKMethods false sun.net.www.http.HttpClient parseHTTPHeader
trace --skipJDKMethods false java.net.SocketInputStream socktRead '#cost > 10000'

5. 咱们最初通过调用栈确认代码执行门路

stack *SocketInputStream socketRead "#cost > 10000"

发现因为 StandbyNameNode 的网络读取数据造成阻塞,到此曾经碰到 native 函数,在 java 层面曾经没有无效办法进行剖析。

这时我看到 StandbyNameNode 的日志:

2020-11-04 18:27:42,583 INFO namenode.RedundantEditLogInputStream (RedundantEditLogInputStream.java:nextOp(177)) - Fast-forwarding stream 'http://cbdp-online1.sdns.financial.cloud:8480/getJournal?jid=hdfs-ha&;segmentTxId=213700&storageInfo=-64%3A272699407%3A1603893889358%3ACID-aa8ec1b5-a501-4195-9299-e14abefbdc11&inProgressOk=true' to transaction ID 184269

同时想起了 @赫炎 提出的思路,有可能是在 JournalNode 端读取 EditLog 文件的时候有阻塞。

6. 咱们在 JournalNode 侧追踪代码调用耗时

trace --skipJDKMethods false org.apache.hadoop.hdfs.qjournal.server.GetJournalEditServlet doGet '#cost > 10000'

发现在调用 java.net.InetSocketAddress.getHostName 处耗时 15s,至此找到了罪魁祸首。

论断:

  1. 经剖析发现在在开启 Kerberos 的状况下,JournalNode 侧响应 getEditLog 接口调用时会进入办法 isValidRequestor,此时会去解析 SecondNameNode 的 hostName,据此搜寻对应的 principal
  2. dns 域名解析服务不能获取 SecondNameNode 的默认地址 0.0.0.0:9868,也即不能解析 0.0.0.0 的 hostName,此处超时 15s 返回,这样每次通过 URLLog 获取 JournalNode 的 EditLog 时,总会有额定耗时 15s,导致 SNN 加载 EditLog 变慢。

为了验证猜测,在每个 JournalNode 节点 hosts 文件配置 0.0.0.0 0.0.0.0,重启 SNN,速度晋升了 20 倍

不得不说,Arthas 作为动静追踪调试 java 过程的神器,真的很不便开发人员定位问题。赞一个!

退出移动版