Arthas 定位 Dubbo 手動註冊 Eureka 異常

做者 | java_keith
來源|阿里巴巴雲原生公衆號java

好久沒有寫技術分享博客,由於發現一個好的工具確實有點忍不住分享一下,畢竟獨樂樂不如衆樂樂。> 這裏須要說的主角就是 Artahs。> Arthas 使用文檔很詳細,我這裏主要記錄一下使用 Arthas 的一點總結。

使用背景

在一個大的團隊裏面,會由於不少歷史緣由或客觀因素致使技術棧並不統一,咱們就遇到這麼一個問題。老項目是使用 Dubbo 框架的 Dubbo 協議進行服務交互,有新的項目是使用 Springcloud 體系的 Feignclient 框架的 Http 協議進行交互。那麼就須要解決兩個問題。spring

  • 問題 1 是 Dubbo 服務須要支持 Dubbo 協議又須要支撐 Http 協議。
  • 問題 2 是 Feignclient 框架可以無損調用 Dubbo 服務的 Http 協議(無損指的是 Dubbo 對 Feignclient 調用方可以作到服務動態感知,負載均衡不須要作二次開發)。

解決思路

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

可是針對問題 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 '#loader=@com.alibaba.dubbo.container.Main@loader,#loader.cachedInstances' 這裏發現了問題,若是是正常被 Load 的 Container 會被存在到 ExtensionLoader 的 CachedInstances 域中(默認的 Spring,log4j存在),可是我自定義的 Container 居然沒找到。
  • ognl '#loader=@com.alibaba.dubbo.container.Main@loader,#loader.exceptions' 這裏發現了之全部沒有加載成功的緣由,在 Exceptions 中有聲明。

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

經過以上分析,問題很是明顯了,在 META-INF 中指定的 Key 重複了。仍是沒深刻理解 Dubbo 中的 Spi 文檔上的‘xxx’是自定義的意思。到這裏修改 Key 之後一切按照計劃執行。源碼分析

結束

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

Arthas 有獎徵文正在進行中!

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

相關文章
相關標籤/搜索