1、前言
對於一個商業專案而言,質量應該是研發同學的生命線。
線上出現了大面積的崩潰或者各種不可用,那畫面簡直美的不敢想象。這也是任何商業專案做大之後都會花大力氣在效能優化與高可用的原因,這個過程中也催生出了各種APM工具及HotFix方案,在一定程度上保障了效能同時提供了一道緊急修復的保障線。
此處提一個問題:假設經過層層流程把關控制的應用線上上還是出現了問題,而HotFix也無法生效,是不是就沒得救了?
2、安全模式的起由
簡單的一句話就是:避免應用在啟動階段崩潰而此時HotFix無法生效,導致的連續、嚴重的無法啟動。
此處舉一個例子:假設應用在啟動階段因為Application中某項出錯而必現崩潰,而拉取熱修復包的操作此時還未發生,那麼這個應用就會陷入連續啟動崩潰的嚴重情形;最終的命運一定是被使用者解除安裝。
那麼應用啟動階段的安全模式就應運而生。
3、安全模式的思考
需要明確的是任何技術都是服務於具體的業務場景,那啟動階段的安全模式就是為了解決啟動階段崩潰卻無法HotFix這種嚴重情形。
我們來思考如下幾個問題:
3.1 什麼會導致啟動階段的崩潰?
現如今各個App在業務上已經發展多年,同時移動端的技術革新也開展多次,那麼應用在啟動階段需要做的事情越來越多,啟動崩潰的誘因可能有:
- 各種檔案包括但不限於資料庫、XML的拷貝或操作失敗;
- 各種網路請求下發了髒資料;
- 各種資源包的下載、合併導致的髒資料,包括但不限於閃屏圖、Zip包、修復包等;
- 使用者由跨N多個版本的低版本App升級到最新版引發的髒資料;
由上可見應用在啟動階段並不安全,在其中任意一環出現問題都將導致嚴重的事故。
3.2 安全模式生效時機?
一般應用都會設定主執行緒的UncaughtExceptionHandler來捕獲執行時的崩潰,很容易想到的就是把安全模式的判定和UncaughtExceptionHandler關聯起來,但是這種做法有很大的缺陷:對Native的異常無能為力,顯然不夠精確;
那我們就採用逆向思維,換種思路:
- 進入應用的時候就記錄一個崩潰次數,在滿足一定條件之後則認為啟動階段沒有異常,同時將崩潰次數重置回覆初始狀態;
- 異常次數到達一定程度則進入安全模式;
需要維護一個崩潰次數:
- 進入應用就把崩潰次數+1;
滿足一定條件則重置崩潰次數:
- 使用者正常退出應用;
- 使用者開啟應用滿10秒;
3.3 安全模式能做什麼?
- 執行預設任務,進行客戶端本地的自主修復,例如:刪除部分快取、清除熱修復包或者別的資源包;
- 清空整個App資料,重置至初始安裝狀態;
- 阻塞程式,優先執行預設任務,例如:請求以及執行熱修復包,等待全部完成之後再執行正常流程;
4、如何設計一個安全模式的庫?
4.1 安全模式應該提供哪些能力?
- 異常啟動的檢測及分級策略:檢測APP啟動異常,同時也細粒度區分知道異常的等級;
- 應用自修復的能力;
- 可以執行同步熱修復的能力;
- 支援獲取詳細崩潰資訊及崩潰的回撥;
4.2 擴充套件性與易用性的設計
- 擴充套件性:
- 對於各家App,安全模式的處理具有共性,但是總有場景是需要定製的,那麼安全模式應該可以執行自定義的策略;
- 易用性:
- App可快速接入,同時可快速驗證策略;
4.3 整體流程圖
5、其它
本文是從設計一個庫的角度來思考應用啟動連續崩潰的處理,現在我非常貼心的為大家推薦一個關於啟動保護的庫:StartUp-Protector:(github.com/liuzhao2007…),使用簡單方便、侵入性低、功能完善、定製化強,歡迎使用:
- 崩潰檢測及分級策略:兩次崩潰執行一級安全模式,三次崩潰執行二級安全模式;
- 提供自修復能力,可自定義進入安全模式的處理策略;
- 提供阻塞程式能力,可執行同步熱修復;
- 提供詳細崩潰資訊的獲取及崩潰的回撥能力;
- 可定製崩潰後策略,例如重啟的忽略策略;
- 提供快速回歸的能力;
歡迎關注微信公眾號:定期分享Java、Android乾貨!