Apache Dubbo是Alibaba開源的高性能RPC框架锌云,在國(guó)內(nèi)有非常多的用戶荠医。
文檔:http://dubbo.incubator.apache.org/zh-cn/
Arthas是Alibaba開源的應(yīng)用診斷利器,9月份開源以來(lái)桑涎,Github Star數(shù)三個(gè)月超過(guò)6000彬向。
當(dāng)Dubbo遇上Arthas,會(huì)碰撞出什么樣的火花呢攻冷?下面來(lái)分享Arthas排查Dubbo問(wèn)題的一些經(jīng)驗(yàn)娃胆。
之前,分享過(guò)如何使用Arthas等曼,見:阿里的Java調(diào)試神器遇到這款I(lǐng)DEA插件里烦,超神!
dubbo-arthas-demo
下面的排查分享基于這個(gè)dubbo-arthas-demo禁谦,非常簡(jiǎn)單的一個(gè)應(yīng)用胁黑,瀏覽器請(qǐng)求從Spring MVC到Dubbo Client,再發(fā)送到Dubbo Server枷畏。
Demo里有兩個(gè)spring boot應(yīng)用别厘,可以先啟動(dòng)server-demo,再啟動(dòng)client-demo拥诡。
Server端:
Arthas快速開始
-https://alibaba.github.io/arthas/install-detail.html
啟動(dòng)后触趴,會(huì)列出所有的java進(jìn)程,選擇1渴肉,然后回車冗懦,就會(huì)連接上ServerDemoApplication
Dubbo線上服務(wù)拋出異常,怎么獲取調(diào)用參數(shù)仇祭?
-https://alibaba.github.io/arthas/watch.html
當(dāng)線上服務(wù)拋出異常時(shí)披蕉,最著急的是什么參數(shù)導(dǎo)致了拋異常?
在demo里,
訪問(wèn)http://localhost:8080/user/0,UserServiceImpl就會(huì)拋出一個(gè)異常,因?yàn)閡ser id不合法乌奇。
在Arthas里執(zhí)行 watch com.example.UserService * -e -x 2 '{params,throwExp}' 没讲,然后再次訪問(wèn),就可以看到watch命令把參數(shù)和異常都打印出來(lái)了礁苗。
怎樣線上調(diào)試Dubbo服務(wù)代碼?
-https://alibaba.github.io/arthas/redefine.html
在本地開發(fā)時(shí)爬凑,可能會(huì)用到熱部署工具,直接改代碼试伙,不需要重啟應(yīng)用嘁信。但是在線上環(huán)境于样,有沒有辦法直接動(dòng)態(tài)調(diào)試代碼?比如增加日志潘靖。
在Arthas里穿剖,可以通過(guò)redefine命令來(lái)達(dá)到線上不重啟,動(dòng)態(tài)更新代碼的效果卦溢。
比如我們修改下UserServiceImpl糊余,用System.out打印出具體的User對(duì)象來(lái):
本地編繹后,把
server-demo/target/classes/com/example/UserServiceImpl.class
傳到線上服務(wù)器,然后用redefine命令來(lái)更新代碼:
這樣子更新成功之后,訪問(wèn) http://localhost:8080/user/1,在ServerDemoApplication的控制臺(tái)里就可以看到打印出了user信息既绕。
怎樣動(dòng)態(tài)修改Dubbo的logger級(jí)別?
-https://alibaba.github.io/arthas/ognl.html
-https://alibaba.github.io/arthas/sc.html
-https://commons.apache.org/proper/commons-ognl/language-guide.html
在排查問(wèn)題時(shí)啄刹,需要查看到更多的信息,如果可以把logger級(jí)別修改為DEBUG凄贩,就非常有幫助。
ognl是apache開源的一個(gè)輕量級(jí)表達(dá)式引擎袱讹。下面通過(guò)Arthas里的ognl命令來(lái)動(dòng)態(tài)修改logger級(jí)別疲扎。
首先獲取Dubbo里TraceFilter的一個(gè)logger對(duì)象,看下它的實(shí)現(xiàn)類捷雕,可以發(fā)現(xiàn)是log4j椒丧。
再用sc命令來(lái)查看具體從哪個(gè)jar包里加載的:
可以看到log4j是通過(guò)slf4j代理的。
那么通過(guò)org.slf4j.LoggerFactory獲取root logger救巷,再修改它的level:
可以看到修改之后壶熏,root logger的level變?yōu)镈EBUG。
怎樣減少測(cè)試小姐姐重復(fù)發(fā)請(qǐng)求的麻煩?
-https://alibaba.github.io/arthas/tt.html
在平時(shí)開發(fā)時(shí)浦译,可能需要測(cè)試小姐姐發(fā)請(qǐng)求過(guò)來(lái)聯(lián)調(diào)棒假,但是我們?cè)赿ebug時(shí),可能不小心直接跳過(guò)去了精盅。這樣子就尷尬了帽哑,需要測(cè)試小姐姐再發(fā)請(qǐng)求過(guò)來(lái)。
Arthas里提供了tt命令叹俏,可以減少這種麻煩妻枕,可以直接重放請(qǐng)求。
上面的tt -t命令捕獲到了3個(gè)請(qǐng)求粘驰。然后通過(guò)tt --play可以重放請(qǐng)求:
Dubbo運(yùn)行時(shí)有哪些Filter? 耗時(shí)是多少?
-https://alibaba.github.io/arthas/trace.html
Dubbo運(yùn)行時(shí)會(huì)加載很多的Filter屡谐,那么一個(gè)請(qǐng)求會(huì)經(jīng)過(guò)哪些Filter處理,F(xiàn)ilter里的耗時(shí)又是多少呢蝌数?
通過(guò)Arthas的trace命令愕掏,可以很方便地知道Filter的信息,可以看到詳細(xì)的調(diào)用棧和耗時(shí)籽前。
Dubbo動(dòng)態(tài)代理是怎樣實(shí)現(xiàn)的?
-.github.io/arthas/jad.html
-com.alibaba.dubbo.common.bytecode.Wrapper
通過(guò)Arthas的jad命令亭珍,可以看到Dubbo通過(guò)javaassist動(dòng)態(tài)生成的Wrappr類的代碼:
獲取Spring context
除了上面介紹的一些排查技巧敷钾,下面分享一個(gè)獲取Spring Context,然后“為所欲為”的例子肄梨。
在Dubbo里有一個(gè)擴(kuò)展
com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory,把Spring Context保存到了里面阻荒。
因此,我們可以通過(guò)ognl命令獲取到众羡。
-SpringExtensionFactory@contexts.iterator.next 獲取到SpringExtensionFactory里保存的spring context對(duì)象
-#context.getBean("userServiceImpl").findUser(1) 獲取到userServiceImpl再執(zhí)行一次調(diào)用
只要充分發(fā)揮想像力侨赡,組合Arthas里的各種命令,可以發(fā)揮出神奇的效果粱侣。
最后
感謝大家看到這里羊壹,如果本文有什么不足之處,歡迎多多指教齐婴;如果你覺得對(duì)你有幫助油猫,請(qǐng)給我點(diǎn)個(gè)贊。
也歡迎大家關(guān)注我的公眾號(hào):程序員麥冬柠偶,每天更新行業(yè)資訊情妖!