DNS解析導致java api獲取本機IP超時

背景

 因爲業務需求導致服務遷移,遷移過程中發現新機房同樣接口的系統響應時間變的異常緩慢(普通有100-200ms的時延)。整個遷移過程中代碼發佈包完全拷貝,所以當時就定位爲系統原因進行排查。

 整個排查過程通過在代碼中關鍵路徑切入耗時監控,從而定位具體耗時部分的代碼,縮小排查範圍。


排查過程

定位的代碼邏輯因爲保密原因省略了很多跟問題無關的代碼,僅列出核心的代碼。

  • try/catch過程中的核心代碼沒有任何耗時的邏輯。
  • finally的處理過程中增加了getLocalIP()方法獲取本地ip地址。
  • 經過添加日誌監控耗時懷疑getLocalIP()方法比較耗時。
    public RecomResult recommend(RequestId reqId, RecomParam condition) {
        lock.readLock().lock();
        long timeStart = System.currentTimeMillis(); 

        try {
            // 省略核心代碼
            return result;
        } catch (Throwable t) {
           // 省略核心代碼
        } finally {
            mapTag.put("ip", engineContext.getLocalIP());
            lock.readLock().unlock();  
        }
    }



getLocalIP()方法的實現邏輯就是調用java api獲取本機ip地址

  • 網上查詢類似文章InetAddress.getLocalHost() 執行很慢開始懷疑DNS解析問題。
  • 通過for循環執行dig命令確認dns解析時好時壞耗時在100-200ms不等。
  • 驗證猜測確認是DNS解析問題,並開始通過本地hosts或緩存本地ip地址減少解析。。
    public String getLocalIP() {

        try {
            if (null == localIp) {
                localIp = InetAddress.getLocalHost().getHostAddress();
            }
        } catch (UnknownHostException e1) {
            LOG.error("get ip failed, e is {}", e1);
        }
        return localIp;
    }


解決方案

解決方案本身分爲代碼本身優化和DNS解析優化。

  • DNS層優化主要是服務器DNS解析增加本地緩存,犧牲DNS解析的時效性。
  • 代碼層面優化主要獲取本地ip地址後緩存只需要進行一次host解析即可。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章