1.前言
ANR比較棘手在于椿猎,沒有崩潰日志惶岭,定位問題比較困難,而且ANR是必須要解決的問題犯眠。
Android對ANR的監(jiān)控機制
Android應用程序是通過消息來驅(qū)動的按灶,Android某種意義上也可以說成是一個以消息驅(qū)動的系統(tǒng),UI筐咧、事件鸯旁、生命周期都和消息處理機制息息相關(guān)噪矛。Android的ANR監(jiān)測方案也是一樣,大部分就是利用了Android的消息機制铺罢。
2.主流的ANR監(jiān)控方案
主流的ANR監(jiān)控方案:FileObserver艇挨,WatchDog,Looper.loop韭赘。它們都各有優(yōu)缺點缩滨,無法覆蓋所有情況,所以在線上使用的時候可以結(jié)合這幾種方案一起使用泉瞻。
2.1 FileObserver實現(xiàn)ANR監(jiān)控
當ANR發(fā)生的時候脉漏,我們是可以通過監(jiān)聽該文件目錄data/anr/的寫入情況來判斷是否發(fā)生了ANR,看起來這是一個不錯的時機袖牙。需要注意的是侧巨,所有應用發(fā)生ANR的時候都會進行回調(diào),因此需要做一些過濾與判斷鞭达,如包名刃泡、進程號等。
優(yōu)點:
- 基于原生接口調(diào)用碉怔,時機和內(nèi)容準確
- 無性能問題實現(xiàn)簡單
缺點:
最大的困難是兼容性問題烘贴,這個方案受限于Android系統(tǒng)的SELinux機制,5.0以后基本已經(jīng)使低權(quán)限應用無法監(jiān)聽到trace文件了撮胧,但是可以在開發(fā)內(nèi)測階段通過root手機進行監(jiān)控桨踪。
2.2 ANR-WatchDog實現(xiàn)ANR監(jiān)控
ANR-WatchDog是參考Android WatchDog機制(com.android.server.WatchDog.java)起個單獨線程向主線程發(fā)送一個變量+1操作的消息,然后自我休眠sleep 自定義ANR的閾值一般是5s芹啥,休眠過后判斷變量是否+1完成锻离,如果未完成則告警。
優(yōu)點:
- 兼容性好墓怀,各個機型版本通用
- 無需修改APP邏輯代碼汽纠,非侵入式
- 邏輯簡單,性能影響不大
缺點:
無法保證能捕捉所有ANR傀履,對閾值的設置直接影響捕獲概率.比如如果設置了5s就無法捕獲10s的Receiver和20s的service 引起的ANR虱朵。
2.3 Looper.loop實現(xiàn)ANR監(jiān)控
巧妙的利用了Android原生Looper.loop中的一個log打印邏輯。
這個log打印邏輯正是在Message消息分發(fā)前后钓账,大部分的性能卡頓問題都是在這里發(fā)生的碴犬,監(jiān)控這兩個邏輯之間的時間差就可以得到當前主線程的卡頓狀態(tài),如果超時則獲取trace信息并上報梆暮。
實現(xiàn)原理:開啟子線程執(zhí)行服协,會消耗cpu資源,謹慎開啟,開發(fā)中一般針對部分用戶下發(fā)開關(guān):
- 設置Looper.setPrinter(自定義printer)實現(xiàn)println方法;
- 在消息執(zhí)行前后,Looper會調(diào)用
Looper.mPriter.pritlin(“>>>>> dispatch msg.target msg.callBack,msg.what”)//子線程開啟收集線程堆棧信息
Looper.mPriter.pritlin(“<<<<<< finish msg.target msg.callBack,msg.what”)//子線程結(jié)束收集線程堆棧信息- 首先需要判斷msg.target的Looper是否等于主線程的Looper.
- 其次計算這兩個函數(shù)前后時間差是否超過200ms超過的話就上報堆棧調(diào)用信息啦粹。
優(yōu)點:
靈活配置可監(jiān)控常見APP應用性能也可作為一部分場景的ANR監(jiān)測,并且可以準確定位ANR和耗時調(diào)用棧。
谷歌已經(jīng)明確標注This must be in a local variable, in case a UI event sets the logger這個looger對象是可以被更改的肥惭,已經(jīng)有開發(fā)者遇到在使用WebView時logger被set為Null導致,進而造成監(jiān)控失敗忍饰。
3.如果dispatchMessage消息執(zhí)行的非常久是無法觸發(fā)監(jiān)控的邏輯。
4.無法監(jiān)控CPU資源緊張造成系統(tǒng)卡頓棒旗,無法響應的ANR
2.4 注冊信號函數(shù)
使用注冊信號函數(shù)機制監(jiān)聽SINGAL_QUIT信號喘批,可以監(jiān)聽ANR和Crash觸發(fā)邏輯撩荣∠橙啵可以作為FileObserver在5.0以后因權(quán)限問題無法監(jiān)測data/anr目錄的使用。
因為當應用發(fā)生crash和ANR的時候餐曹,系統(tǒng)會向目標進程發(fā)送SIGNAL_QUIT信號逛拱,應用虛擬機捕獲到信號以后會收集系統(tǒng)信息輸出到日志文件中(data/anr/trace.txt)然后kill掉目標進程。trace文件中數(shù)據(jù)過大台猴,可以根據(jù)當前時間節(jié)點和進程id進行信息過濾朽合。詳情參考:讓Native Crash 與ANR無處發(fā)泄
3.總結(jié)
ANR監(jiān)控方案各有優(yōu)劣,開發(fā)中一般組合多個共同使用饱狂。
Crash,ANR,卡頓最難的是異常信息的收集上傳曹步,收集到信息后可以根據(jù)日志進行分析進而解決問題。信息(一般是將日志保存在本地休讳,有效期限是七天)上傳一般都是通過開關(guān)動態(tài)下發(fā)的讲婚,目的是為了節(jié)省帶寬和服務端的存儲壓力。千萬級的用戶數(shù)據(jù)量會很大俊柔。
在灰度期間重點觀察指標是否正常筹麸,如果正常擴大灰度繼續(xù)觀察,不正常的話就停止灰度雏婶。然后定位問題是升級還是采用熱修復物赶。