Hadoop源碼分析-Namenode 安全模式源碼深度剖析

本文繼續(xù) NameNode 啟動流程源碼剖析,之前講解了

  1. Namenode 啟動流程跟蹤
  2. Namenode Httpserver 啟動流程跟蹤
  3. Namenode 元數(shù)據(jù)加載跟蹤
    這次講解下: Namenode 資源檢查和是否進(jìn)入安全模式的判斷

一、 Namenode 安全模式源碼分析:資源檢查

我們在啟動 Namenode 的時候,有時會遇到 Namenode 進(jìn)入安全模式,所以我們一起也來看看這邊吧。Namenode 安全模式的代碼藏的比較隱蔽,而且名字起的也很隨意。

  1. NameNode 服務(wù)啟動跟蹤 的第 4 步,最后有一句代碼startCommonServices(conf); 這個方法,這個代碼看著很普通,但其實(shí)資源檢查和安全模式都在這里(吐槽下方法名起不直接)

    image

  2. 我們進(jìn)入到 startCommonServices(conf);方法,可以看到在 rpcServer 啟動前,又調(diào)用了namesystem.startCommonServices(conf, haContext);,我們繼續(xù)跟進(jìn):

    startCommonServices

  3. 進(jìn)入 namesystem.startCommonServices(conf, haContext); 方法后,里面的代碼就要注意了(這里代碼的命名都比較不好,容易忽略)
    首先要注意 nnResourceChecker = new NameNodeResourceChecker(conf); ,NameNodeResourceChecker 這個就是 Namenode 的資源檢查,我們跟進(jìn):

    startCommonServices

  4. 跟進(jìn) nnResourceChecker = new NameNodeResourceChecker(conf); 后,發(fā)現(xiàn)這里是獲得了很多 Namenode 的資源目錄,包含editlog存儲目錄(共享、非共享)、Namenode 配置文件中配置的必須目錄等,這些目錄都是通過配置文件配置的
    然后把這些目錄傳入了 addDirToCheck 方法,我們繼續(xù)跟進(jìn)addDirToCheck方法

    NameNodeResourceChecker

  5. 跟進(jìn)addDirToCheck方法后,發(fā)現(xiàn)這里把 所有的目錄都包裝成 CheckedVolume 對象然后又 put 到 volumes 變量中,volumes 變量是個Map集合,到這里第4步中的 nnResourceChecker = new NameNodeResourceChecker(conf); 構(gòu)造函數(shù)算是執(zhí)行完了,我們繼續(xù)第 4步中的下一步checkAvailableResources()

    image

  6. 跟進(jìn) checkAvailableResources(),后發(fā)現(xiàn)就一行代碼,繼續(xù)跟進(jìn),發(fā)現(xiàn)雖然還是一行代碼,但是這里把第 5步中的 volumes 當(dāng)做參數(shù)傳過去了,繼續(xù)跟進(jìn)

    image

    image

  7. 這里就是對所有傳進(jìn)來的目錄都進(jìn)行了校驗(yàn),具體的校驗(yàn)方法就是 resource.isResourceAvailable(),再看看這個方法

    isResourceAvailable

  8. 此方法是個抽象方法,需要知道它的實(shí)現(xiàn),我們在第5步的時候知道其實(shí)這些目錄都被封裝成了CheckedVolume對象,所以這個方法的實(shí)現(xiàn)類就是CheckedVolume。

    image

  9. 進(jìn)入CheckedVolumeisResourceAvailable方法后,發(fā)現(xiàn)這里 其實(shí)就是判斷此目錄的剩余空間是否小于某個值availableSpace < duReserved(這個值是100m,具體看配置吧),如果小于配置的值,則返回false,否則是 true。到這里這邊 checkAvailableResources 方法的執(zhí)行就完成了。

    image

二、Namenode 安全模式源碼分析:block數(shù) 檢查

  1. 其實(shí)從6~9就是在給FSNamesystem.hasResourcesAvailable變量賦值為true或false。我們繼續(xù)6中的代碼,也就是startCommonServices中的下一步,這里有這樣一行代碼 setBlockTotal();,這個代碼里就是 啟動安全模式 的關(guān)鍵(但是名字起的太普通了)
    image
  2. 我們跟進(jìn)setBlockTotal();,這里先看 getCompleteBlocksTotal() 方法,看方法名應(yīng)該是獲得 完成的block總數(shù)。這里要解釋下,其實(shí)在 HDFS中的 block 包含兩個狀態(tài) 一個是 Complete ,另一個是 UnderConstruction。這里就是獲得 Complete 狀態(tài)的block數(shù)量。
    setBlockTotal
  3. 我們跟進(jìn)getCompleteBlocksTotal 方法看看,看到getBlocksTotal() - numUCBlocks;這個代碼,我們應(yīng)該了解到 complete狀態(tài)的block數(shù)就是使用 總的block減去 UnderConstruction 狀態(tài)的 block數(shù)。具體判斷狀態(tài),就不看了
    getCompleteBlocksTotal
  4. 我們繼續(xù)跟進(jìn)safeMode.setBlockTotal方法,注意到這里計算了兩個值 blockThresholdblockReplQueueThreshold,最后又調(diào)用了checkMode()方法
    safeMode.setBlockTotal
  5. 跟進(jìn) checkMode()方法,此方法中needEnter()如果返回true就會觸發(fā)enter()(enter就是進(jìn)入安全模式),然后我們看看needEnter()方法具體的邏輯
    checkMode
  6. 進(jìn)入 needEnter()后,看到代碼比較簡單,就是有三個判斷,只要有任何一個是True,就返回True。那我們仔細(xì)看看這三個條件吧
    needEnter
  • 條件1、 (threshold != 0 && blockSafe < blockThreshold)
    如果 blcok 閾值不等于0,且 安全模塊(blockSafe) 小于 閾值模塊
    blockSafe:只要有一個副本就是 blockSafe

  • 條件2、 (datanodeThreshold != 0 && getNumLiveDataNodes() < datanodeThreshold)
    如果 dataNode 活躍最小閾值不等于0,且活躍的 DataNodes 小于最小閾值時,進(jìn)入安全模式
    datanodeThreshold 默認(rèn)為0,由 dfs.namenode.safemode.min.datanodes 指定
    LiveDataNodes: 當(dāng)前時間 - DataNodes 心跳最后的時間 < 10分30秒

  • 條件3、(!nameNodeHasResourcesAvailable());
    如果,NameNode 資源檢查無效,進(jìn)入安全模式

三、Namenode 安全模式源碼分析:獲取Datanode活躍數(shù)

前兩節(jié)分析的就是 第1個條件和第3個條件,而第2個條件并沒有分析,我們這一節(jié)就看看這個代碼。


needEnter
  1. 先看 datanodeThreshold 在哪里賦值的,通過搜索發(fā)現(xiàn)該變量是在配置文件中配置的,dfs.namenode.safemode.min.datanodes,默認(rèn)值是0,所以默認(rèn)情況下,2 這個條件直接就不判斷了。但是我們還可以繼續(xù)看看判斷Datanode活躍的代碼。
    image
  2. 跟進(jìn) getNumLiveDataNodes(),看到就一句代碼
    image
  3. 繼續(xù)跟進(jìn) .getNumLiveDataNodes();,可以看到,判斷Datanode是否活躍的主要代碼其實(shí)就是 !isDatanodeDead(dn),也就是說,不是死亡的 datanode就是活躍的
    image
  4. 繼續(xù)跟進(jìn) !isDatanodeDead(dn) ,可以看到就一句代碼,此代碼就是計算 datanode是否死亡的代碼。node.getLastUpdateMonotonic() 就是最后一次心跳的時間 ,monotonicNow()就是當(dāng)前時間,heartbeatExpireInterval是心跳過期間隔;
    所以計算公式就是:
    如果 當(dāng)前時間 - 最后一次心跳時間 > 心跳過期間隔 那么就認(rèn)為Datanode死亡了。
    image
  5. 最后看看 heartbeatExpireInterval 是多少呢?
    heartbeatRecheckInterval 默認(rèn)是5分鐘, heartbeatIntervalSeconds默認(rèn)是3秒,他們在配置文件里都有配置,具體代碼就不跟了。
    image

4. 總結(jié)

到此:Namenode 安全模式的代碼就分析完了。這里畫個圖簡單的描述情況


image

點(diǎn)擊這里查看原文地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容