1. 程式人生 > 其它 >Arthas 定位 Dubbo 手動註冊 Eureka 異常

Arthas 定位 Dubbo 手動註冊 Eureka 異常

技術標籤:雲原生開源arthasDubbo中介軟體

作者 | java_keith
來源|阿里巴巴雲原生公眾號

很久沒有寫技術分享部落格,因為發現一個好的工具確實有點忍不住分享一下,畢竟獨樂樂不如眾樂樂。> 這裡需要說的主角就是 Artahs。> Arthas 使用文件很詳細,我這裡主要記錄一下使用 Arthas 的一點總結。

使用背景

在一個大的團隊裡面,會因為很多歷史原因或客觀因素導致技術棧並不統一,我們就遇到這麼一個問題。老專案是使用 Dubbo 框架的 Dubbo 協議進行服務互動,有新的專案是使用 Springcloud 體系的 Feignclient 框架的 Http 協議進行互動。那麼就需要解決兩個問題。

  • 問題 1 是 Dubbo 服務需要支援 Dubbo 協議又需要支撐 Http 協議。

  • 問題 2 是 Feignclient 框架能夠無損呼叫 Dubbo 服務的 Http 協議(無損指的是 Dubbo 對 Feignclient 呼叫方能夠做到服務動態感知,負載均衡不需要做二次開發)。

解決思路

有了以上的目標,我們就需要想辦法解決問題。解決第一個問題倒是比較容易,Dubbo 本身就提供的 Http 協議暴漏。也就是將老工程 Dubbo 升級、配置兩種協議問題一就這麼解決了。

但是針對問題 2,我們可以羅列一下遇到的問題。Dubbo 註冊使用的是 zk 註冊中心,Springcloud 工程使用 Eureka 註冊中心。這裡順帶也要讚美一下 Feignclient 框架,Feignclient 接入服務的門檻很低,這樣相容了很多語言、環境等帶來的差異,也就是說只要是 http 協議的介面 Feignclient 就能呼叫。到這裡實際上通過 Feignclient 直接呼叫 Dubbo 服務暴漏的 Http 協議介面是能夠走的通,只不過沒法做到負載均衡,失敗轉移等能力。說了這麼多總結一下吧。

  • 現在通過 Feignclient 直連 Dubbo 框架工程的 Http 協議能夠正常執行。

  • 分散式環境下需要解決直連的弊端(無法負載均衡,無法失敗轉移,無法動態擴容等等) 好在通過分析了 Eureka 原始碼以後打開了另一個大門,Eureka 實際上是獨立的元件,而且提供手動註冊服務的能力(即使沒有修改原始碼就有了)。現在解決思路就是在 Dubbo 工程裡面引入 Eureka 元件,手動將服務註冊到 Eureak 以便 Feignclient 能夠無損呼叫。

主角(Arthas)登場

為了將 Dubbo 框架工程提供註冊 Eureka 的能力,並且能夠做到優雅上線和下線。我們主要是藉助了 Dubbo 的 Spi 擴充套件能力中的 Container 擴充套件。程式碼如下:

class EurekaDubboContainer implements Container {...}

有了以上程式碼還需要做一件重要的事情,就是宣告 Container 的全路徑。META-INF/dubbo/org.apache.dubbo.container.Container:xxx=com.xxx.XxxContainer,當時我們配置這裡的程式碼 spring=com.xxx.EurekaDubboContainer,當所有準備好了以後我們啟動工程,發現無異常輸出,程序完美。但是 Deignclient 怎麼也無法呼叫。最主要是啟動過程中沒有任何異常輸出,經過大量論證後,就在快絕望的時候,我發現了 Arthas,Arthas 可以檢視記憶體中物件屬性值以及執行物件的方法,我欣喜若狂。通過之前對 Dubbo 註冊過程原始碼分析:

com.alibaba.dubbo.common.extension.ExtensionLoader#loadFile
} catch (Throwable t) {
  IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + url + ", cause: " + t.getMessage(), t);
  exceptions.put(line, e);
}

在 Dubbo 啟動過程,會從 Jar 包中掃描配置的 META-INF 中配置的 Container,在載入的時候這個異常是直接存放在了 Loader 類的域中,猜測可能是為了解決 Container 隔離所以異常並沒有丟擲。當前主要目標還是分析為啥我定義的擴充套件容易沒有啟動。部署 Arthas 以後我開始了分析之路。

  • sc -d *.EurekaDubboContainer 發現類已經正常載入,說明有被 Load 載入。

  • jad *.EurekaDubboContainer 發現載入的類程式碼也是在正常(排除包不對的可能)。

  • ognl ‘#[email protected]@loader,#loader.cachedInstances’ 這裡發現了問題,如果是正常被 Load 的 Container 會被存在到 ExtensionLoader 的 CachedInstances 域中(預設的 Spring,log4j存在),但是我自定義的 Container 竟然沒找到。

  • ognl ‘#[email protected]@loader,#loader.exceptions’ 這裡發現了之所有沒有載入成功的原因,在 Exceptions 中有宣告。

0CA166B6-DF7E-41eb-B6D2-014A00AEABDB.png

通過以上分析,問題非常明顯了,在 META-INF 中指定的 Key 重複了。還是沒深入理解 Dubbo 中的 Spi 文件上的‘xxx’是自定義的意思。到這裡修改 Key 以後一切按照計劃執行。

結束

通過一波操作,我們發現從技術角度出發,其實沒有解決不了的問題,只是需要多想一想,多想想辦法總可以找到的。包括使用 Arthas 上 Ognl 如何檢視 Load 例項中的非靜態域,直接獲取是無法獲取的,因為沒有存在在 Arthas 上下文中,所以變通一下思路:通過 Main 的靜態域獲取例項,再通過例項變數獲取非靜態域的值。技術沒有終止,願你我一同進步。為開源貢獻微薄的力量。若對細節有興趣的朋友,可留言交流。

Arthas 有獎徵文正在進行中!

為了讓更多開發者開始用上 Arthas 這個 Java 診斷神器,今年 3 月 26 日,Arthas 社群聯合 JetBrains 推出Arthas 有獎徵文活動:**聊聊這些年你和 Arthas 之間的那些事兒。**活動已進行至第七期,點選連結即可參與:http://alibabacloud.mikecrm.com/9khcRrs,歡迎大家踴躍投稿,參與即有可能獲獎!