一. 問(wèn)題描述
在幾天前,現(xiàn)場(chǎng)技術(shù)反饋應(yīng)用的支付二維碼是過(guò)期圖片(上一筆交易記錄的支付二維碼).并隨時(shí)甩了一堆的日志.于是一場(chǎng)耗費(fèi)4务荆、5天的戰(zhàn)斗正式打響.
二. 問(wèn)題分析
由于版本正在改版階段,邏輯確實(shí)發(fā)生了一些變動(dòng),初步分析,認(rèn)為是由于過(guò)期的二維碼刷新延遲導(dǎo)致用戶(hù)掃到了前一筆訂單的支付二維碼信息了.但分析日志后,發(fā)現(xiàn)問(wèn)題并沒(méi)有那么簡(jiǎn)單.
1.一般情況下以現(xiàn)在的網(wǎng)絡(luò)條件.2穷遂、3秒內(nèi)就可以完成二維碼的刷新操作.
2.分析日志.
GetInCarDataByOutCarNoRequest>>>{parkid=0, outDspIp=172.19.2.3, serialType=0, outCarNo=xxx, etcNo=000000, extParam=}
....
接口沒(méi)有返回值,同時(shí)拿了后臺(tái)的日志,也沒(méi)有任何請(qǐng)求信息.可以發(fā)現(xiàn)請(qǐng)求沒(méi)有被服務(wù)器所接收.并且客戶(hù)端沒(méi)有任何的異常信息記錄.
3.現(xiàn)場(chǎng)有些機(jī)子反饋沒(méi)問(wèn)題函匕,有些機(jī)子反饋有問(wèn)題.(10臺(tái)機(jī)子,2臺(tái)運(yùn)行過(guò)程中就不再顯示二維碼了).
三. 問(wèn)題排查過(guò)程
這讓我陷入了兩難的境地,深入排查出問(wèn)題的邏輯方法也看不出什么異常.
我們決定在該請(qǐng)求接口中埋點(diǎn)日志
在主要的調(diào)用方法上補(bǔ)上了try/catch,希望能夠獲取到異常信息
通過(guò)對(duì)比穩(wěn)定版本,我們決定取消引入multidex分包(該方案主要解決64K方法數(shù)限制問(wèn)題)
但是很遺憾的是,在以上的努力之后,我們的問(wèn)題依然在發(fā)生,BUG仍在肆孽
是的(主要是Google自家的圖片加載引擎Glide 3.7.1,特別注意.回退后的版本在加載GIF圖片時(shí)存在閃爍的問(wèn)題.在不跳大版本的情況下推薦使用3.8.0).
基本已可以確認(rèn)是第三方庫(kù)的問(wèn)題.但是為什么日志上顯示不了呢?.在一次無(wú)關(guān)緊要的復(fù)現(xiàn)過(guò)程中,激發(fā)了一個(gè)想法.是不是還有其他地方消費(fèi)掉了異常信息呢?經(jīng)過(guò)排查EventBus自行消費(fèi)掉了異常.但它又沒(méi)強(qiáng)制處理.導(dǎo)致異常無(wú)故消失。
void invokeSubscriber(Subscription subscription, Object event) {
try {
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
} catch (InvocationTargetException e) {
handleSubscriberException(subscription, event, e.getCause());
} catch (IllegalAccessException e) {
throw new IllegalStateException("Unexpected exception", e);
}
}
private void handleSubscriberException(Subscription subscription, Object event, Throwable cause) {
if (event instanceof SubscriberExceptionEvent) {
...
} else {
if (throwSubscriberException) {
throw new EventBusException("Invoking subscriber failed", cause);
}
if (logSubscriberExceptions) {
logger.log(Level.SEVERE, "Could not dispatch event: " + event.getClass() + " to subscribing class "
+ subscription.subscriber.getClass(), cause);
}
if (sendSubscriberExceptionEvent) {
SubscriberExceptionEvent exEvent = new SubscriberExceptionEvent(this, cause, event,subscription.subscriber);
post(exEvent);
}
}
}
可以看到.出現(xiàn)一些異常的情況下,它會(huì)處理一些感興趣的異常,但是不強(qiáng)制用戶(hù)去處理.我們丟掉的就是這塊內(nèi)容的異常了.(當(dāng)然截止目前,SubscriberExceptionEvent異常已經(jīng)會(huì)被處理).
四. 經(jīng)驗(yàn)總結(jié)
- 該問(wèn)題正好進(jìn)入了我們遺失日志的陰暗角落,給我們排查問(wèn)題上增加了很大的麻煩.總讓人不知所措(超出個(gè)人的認(rèn)知)蚪黑,無(wú)從下手.出現(xiàn)問(wèn)題的時(shí)候,日志是我們最主要的依靠手段.善待日志也是善待自己.
- 做好第一點(diǎn)的情況下盅惜,出現(xiàn)大海撈針的情況就會(huì)變少.但即使出現(xiàn)了.靜下心去排查那些看似無(wú)厘頭的BUG.
- 遇到無(wú)從下手的問(wèn)題時(shí),又趕上急需發(fā)版確實(shí)是一種折磨.該版本測(cè)試流程已經(jīng)走完.但是在測(cè)試環(huán)境上始終無(wú)法重現(xiàn).為定位問(wèn)題所在增加了很大的困難。通過(guò)日志以及領(lǐng)導(dǎo)爭(zhēng)取的現(xiàn)場(chǎng)測(cè)試環(huán)境為該問(wèn)題的的最終解決帶來(lái)了很大的幫助.逐漸縮小排查范圍.
- 理論上第三方依賴(lài)庫(kù)高版本會(huì)修復(fù)低版本發(fā)現(xiàn)的問(wèn)題.但是同時(shí)也會(huì)引入新的問(wèn)題.特別是跨版本升級(jí).就目前來(lái)看應(yīng)該是在使用新版本Glide(4.3.1)導(dǎo)致引入BUG(但尚無(wú)精確判定).所以在使用第三方庫(kù)時(shí)忌穿,盡量事先查看該版本修復(fù)的BUG,以及issue列表.