前言
Android 穩(wěn)定性?xún)?yōu)化是一個(gè)需要長(zhǎng)期投入折汞,持續(xù)運(yùn)營(yíng)和維護(hù)的一個(gè)過(guò)程,不僅深入探討了 Java Crash、Native Crash 和 ANR 的解決流程及方案踩官,還分析了其內(nèi)部實(shí)現(xiàn)原理和監(jiān)控流程钾怔。本文對(duì)穩(wěn)定性?xún)?yōu)化方面的知識(shí)做了一個(gè)全面總結(jié)碱呼,主要內(nèi)容如下:
如何提升App的穩(wěn)定性
一般性的App能接觸到穩(wěn)定性的需求其實(shí)并不多,只有大型的處于穩(wěn)定運(yùn)營(yíng)期的App才會(huì)重視App的穩(wěn)定性宗侦,穩(wěn)定性實(shí)際上是一個(gè)大問(wèn)題愚臀,一個(gè)穩(wěn)定的產(chǎn)品才能夠保證用戶(hù)的留存率,所以穩(wěn)定性是質(zhì)量體系中最基本也是最關(guān)鍵的一環(huán):
- 穩(wěn)定性是大問(wèn)題矾利,Crash是P0優(yōu)先級(jí):對(duì)于用戶(hù)來(lái)說(shuō)很難容忍你的應(yīng)用發(fā)生崩潰
- 穩(wěn)定性可優(yōu)化的面很廣:不僅僅是指崩潰姑裂,像卡頓、耗電等也屬于穩(wěn)定性?xún)?yōu)化的范疇男旗,對(duì)于移動(dòng)端高可用這個(gè)標(biāo)準(zhǔn)來(lái)說(shuō)舶斧,性能優(yōu)化只是高可用的一部分,還有一部分就是應(yīng)用業(yè)務(wù)流程功能上的可用
穩(wěn)定性維度
- Crash維度:一般會(huì)將Crash單獨(dú)作為一項(xiàng)重要指標(biāo)進(jìn)行突破察皇,最常見(jiàn)的統(tǒng)計(jì)指標(biāo)就是Crash率茴厉,后面會(huì)說(shuō)到
- 性能維度:?jiǎn)?dòng)速度、內(nèi)存什荣、卡頓矾缓、流量、電量等等稻爬,在解決應(yīng)用的Crash之后嗜闻,就應(yīng)該著手保障性能體系的穩(wěn)定
- 業(yè)務(wù)高可用維度:業(yè)務(wù)層面的高可用是相當(dāng)關(guān)鍵的一步,需要使用多種手段去保障App業(yè)務(wù)的主流程及核心路徑的可用性
穩(wěn)定性?xún)?yōu)化概述
如果App到了線(xiàn)上才發(fā)現(xiàn)異常因篇,其實(shí)已經(jīng)造成了損失泞辐,所以穩(wěn)定性?xún)?yōu)化重點(diǎn)在于預(yù)防
- 重在預(yù)防、監(jiān)控必不可少:從開(kāi)發(fā)到測(cè)試到發(fā)布上線(xiàn)運(yùn)維這些各個(gè)階段都需要預(yù)防異常的發(fā)生竞滓,或者說(shuō)要將發(fā)生異常造成的損失降到最低咐吼,用最小的代價(jià)暴露最多的問(wèn)題,同時(shí)監(jiān)控也是必不可少的一步商佑,需要擁有一定的監(jiān)控手段來(lái)更加靈敏的發(fā)現(xiàn)問(wèn)題
- 思考更深一層锯茄、重視隱含信息:比如你發(fā)現(xiàn)了一個(gè)崩潰,但是你不能簡(jiǎn)單的只看這一個(gè)崩潰,要考慮這個(gè)崩潰是不是在其他地方也有同樣或者類(lèi)似的肌幽,如果有就考慮是否統(tǒng)一處理晚碾,今后該如何預(yù)防,總結(jié)經(jīng)驗(yàn)
- 長(zhǎng)效保持需要科學(xué)流程:在項(xiàng)目的每一個(gè)階段建立完善的相關(guān)規(guī)范喂急,保證長(zhǎng)效的優(yōu)化效果
如何有效降低應(yīng)用崩潰率
Crash相關(guān)指標(biāo)
1.UV格嘁、PV Crash率
- UV Crash率:等于Crash UV/DAU:主要針對(duì)于用戶(hù)使用量的統(tǒng)計(jì),它統(tǒng)計(jì)一段時(shí)間內(nèi)所有用戶(hù)中發(fā)生過(guò)崩潰的用戶(hù)占比廊移,和UV強(qiáng)相關(guān)糕簿,UV是指Unique Visitor一天內(nèi)訪問(wèn)網(wǎng)站的人數(shù)(是以cookie為依據(jù)),一天內(nèi)同一訪客的多次訪問(wèn)只計(jì)算為1狡孔,一臺(tái)電腦不同的瀏覽器的cookie值不同懂诗。
- PV Crash率:針對(duì)用戶(hù)使用頻率的統(tǒng)計(jì),統(tǒng)計(jì)一段時(shí)間內(nèi)所有用戶(hù)啟動(dòng)次數(shù)中發(fā)生崩潰的占比苗膝,和PV強(qiáng)相關(guān)殃恒,PV是指PageView也就是頁(yè)面點(diǎn)擊量,每次刷新就算一次瀏覽辱揭,多次打開(kāi)同一頁(yè)面會(huì)累加离唐。
- UV Crash方便評(píng)估用戶(hù)影響范圍,PV Crash方便評(píng)估相關(guān)Crash的影響嚴(yán)重程度
- 注意:沿用同一種衡量方式:不管你是使用UVCrash還是PVCrash作為主要指標(biāo)界阁,你應(yīng)該一直使用它侯繁,因?yàn)楹虲rash率相關(guān)的會(huì)有一些經(jīng)驗(yàn)值,這些經(jīng)驗(yàn)值需要對(duì)應(yīng)一個(gè)衡量指標(biāo)
2.Java泡躯、Native Crash率
- Java Crash:在Java代碼中贮竟,出現(xiàn)了未捕獲的異常,導(dǎo)致程序異常退出
- Native Crash:一般都是因?yàn)樵贜ative代碼中訪問(wèn)非法地址较剃,也可能是地址對(duì)齊出現(xiàn)了問(wèn)題咕别,或者發(fā)生了程序主動(dòng)abort,這些都會(huì)產(chǎn)生相應(yīng)的signal信號(hào)写穴,導(dǎo)致程序異常退出惰拱。目前Native崩潰中最成熟的方案是BreakPad。
3.啟動(dòng)啊送、重點(diǎn)流程Crash率
- 啟動(dòng)Crash率:在啟動(dòng)階段用戶(hù)還沒(méi)有完全打開(kāi)就發(fā)生了崩潰的占比偿短,只要是用戶(hù)打開(kāi)App10s之內(nèi)發(fā)生的崩潰都被視為啟動(dòng)Crash,它是Crash分類(lèi)中最嚴(yán)重的一類(lèi)馋没,我們需要重點(diǎn)關(guān)注這個(gè)指標(biāo)昔逗,而且降低的越低越好,并且我們應(yīng)該結(jié)合客戶(hù)端的容災(zāi)策略進(jìn)行自主修復(fù)
4.增量篷朵、存量Crash率
- 增量Crash:指新增Crash勾怒,它是新版本Crash率變動(dòng)的原因婆排,如果沒(méi)有新增的Crash,那么新版本的Crash率應(yīng)該是和老版本Crash率保持一致笔链,所以增量Crash是新版本中需要重點(diǎn)解決的問(wèn)題
- 存量Crash:指老版本中已經(jīng)存在的Crash段只,這些Crash一般都是難以解決或者是需要在特定場(chǎng)景下才會(huì)出現(xiàn)的難以復(fù)現(xiàn)的問(wèn)題,這類(lèi)問(wèn)題需要長(zhǎng)期投入精力持續(xù)解決
- 優(yōu)先解決增量鉴扫、持續(xù)跟進(jìn)存量
5.Crash率評(píng)價(jià)指標(biāo)
- 務(wù)必在千分之二以下:Java和Native的崩潰率加起來(lái)需要在千分之二以下才能算是合格的
- Crash率處于萬(wàn)分位視為優(yōu)秀的標(biāo)準(zhǔn)
Crash關(guān)鍵問(wèn)題
1.盡可能還原Crash現(xiàn)場(chǎng)
一旦發(fā)生崩潰赞枕,我們需要盡可能保留崩潰現(xiàn)場(chǎng)信息,這樣有利于還原崩潰發(fā)生時(shí)的各種場(chǎng)景信息坪创,從而推斷出可能導(dǎo)致崩潰的原因鹦赎,對(duì)于采集環(huán)節(jié)可以參考以下采集點(diǎn):
- 采集堆棧、用戶(hù)設(shè)備误堡、OS版本、發(fā)生崩潰的進(jìn)程雏吭、線(xiàn)程名锁施、崩潰前后的Logcat
- 前后臺(tái)、使用時(shí)長(zhǎng)杖们、App版本悉抵、小版本、渠道
- CPU架構(gòu)摘完、內(nèi)存信息姥饰、線(xiàn)程數(shù)、資源包信息孝治、行為日志
上面是一張Bugly后臺(tái)的截圖列粪,對(duì)于成熟的性能監(jiān)控平臺(tái)不僅有Crash的單獨(dú)信息,同時(shí)會(huì)對(duì)各種Crash進(jìn)行聚合以及報(bào)警谈飒。
2.APM后臺(tái)聚合展示
- Crash現(xiàn)場(chǎng)信息:包括Crash具體堆棧信息及其它額外信息
- Crash Top機(jī)型岂座、OS版本、分布版本杭措、發(fā)生地域:有了這些Top Crash信息之后就能夠知道哪些Crash的影響范圍比較大需要重點(diǎn)關(guān)注
- Crash起始版本费什、上報(bào)趨勢(shì)、是否新增手素、持續(xù)版本鸳址、發(fā)生量級(jí)等等:可以從多個(gè)視角判斷Crash發(fā)生的可能原因以及決定是否需要修復(fù),在哪些版本上進(jìn)行修復(fù)
3.Crash相關(guān)的整體架構(gòu)
4.非技術(shù)相關(guān)的關(guān)鍵問(wèn)題
建立規(guī)范的流程保證開(kāi)發(fā)人員能夠及時(shí)處理線(xiàn)上發(fā)生的問(wèn)題:
- 專(zhuān)項(xiàng)小組輪值:成立專(zhuān)門(mén)小組來(lái)跟蹤每個(gè)版本周期之內(nèi)線(xiàn)上產(chǎn)生的Crash泉懦,保證一定有人跟進(jìn)處理
- 自動(dòng)分配匹配:可以自定義某些業(yè)務(wù)模塊名稱(chēng)稿黍,自動(dòng)分配給相應(yīng)人員處理
- 處理流程全紀(jì)錄:記錄相應(yīng)人員處理Crash的每一步,后期出現(xiàn)問(wèn)題追究相關(guān)責(zé)任人也是有據(jù)可查的
單個(gè)Crash處理方案
- 根據(jù)堆棧及現(xiàn)場(chǎng)信息找答案:一般來(lái)說(shuō)堆棧信息可以幫助我們解決90%的問(wèn)題
- 找共性比如機(jī)型祠斧、OS闻察、實(shí)驗(yàn)開(kāi)關(guān)、資源包等:有些Crash信息通過(guò)堆棧找不到有用的幫助,不能直接解決辕漂,這種情況下可以通過(guò)Crash發(fā)生時(shí)的各種現(xiàn)場(chǎng)信息作輔助判斷呢灶,分析這些Crash用戶(hù)擁有哪些共性
- 線(xiàn)下復(fù)現(xiàn)、遠(yuǎn)程調(diào)試:有了共性之后嘗試在線(xiàn)下進(jìn)行復(fù)現(xiàn)钉嘹,或者嘗試能否進(jìn)行遠(yuǎn)程調(diào)試
Crash率治理方案
- 解決線(xiàn)上常規(guī)Crash:抽出一定時(shí)間來(lái)專(zhuān)門(mén)解決所有常規(guī)的Crash鸯乃,這些Crash一般相對(duì)來(lái)說(shuō)比較容易解決
- 系統(tǒng)級(jí)Crash嘗試Hook繞過(guò):當(dāng)然Android系統(tǒng)版本一直在不斷的升級(jí),隨著新系統(tǒng)的覆蓋率越來(lái)越高跋涣,老版本的系統(tǒng)Bug可能會(huì)逐漸減少
- 疑難Crash重點(diǎn)突破缨睡、更換方案:做到長(zhǎng)期跟蹤,團(tuán)隊(duì)合作重點(diǎn)突破陈辱,實(shí)在不行可以考慮更換實(shí)現(xiàn)方案
通過(guò)以上幾點(diǎn)應(yīng)該可以解決大部分的存量Crash奖年,同時(shí)再控制好新增Crash,這樣一來(lái)整體的Crash率一般都能夠得到有效降低沛贪。
這一部分的內(nèi)容有點(diǎn)雜而多陋守,一般也是需要多端配合,所以不太好做具體演示利赋,大家可以在網(wǎng)上多查找相關(guān)資料進(jìn)行鞏固學(xué)習(xí)水评。
如何選擇合適的崩潰服務(wù)
- 騰訊Bugly: 除了有crash數(shù)據(jù)還有運(yùn)營(yíng)數(shù)據(jù)
- UC 啄木鳥(niǎo):可以捕獲Java、Native異常媚送,被系統(tǒng)強(qiáng)殺的異常中燥,ANR,Low Memory Killer塘偎、killProcess疗涉。技術(shù)深度以及捕獲能力強(qiáng)
- 網(wǎng)易云捕:繼承便捷,訪問(wèn)快式塌,捕獲以及上報(bào)速度及時(shí)博敬,支持實(shí)時(shí)報(bào)警,提供多種報(bào)警選項(xiàng)峰尝,可以自定義參數(shù)偏窝。
- Google的Firebase
- crashlytics:服務(wù)器在國(guó)外,訪問(wèn)速度慢武学,會(huì)丟掉數(shù)據(jù)
- 友盟:crash之后會(huì)在再次啟動(dòng)的時(shí)候上報(bào)數(shù)據(jù)祭往,所以不能立即獲得這部分信息
移動(dòng)端業(yè)務(wù)高可用方案
移動(dòng)端高可用方案不僅僅是指性能方面的高可用,業(yè)務(wù)方面的高可用也是尤為重要的火窒,如果業(yè)務(wù)都走不通硼补,試問(wèn)你性能做的再好又有何用呢?
- 高可用:性能+業(yè)務(wù)
- 業(yè)務(wù)高可用側(cè)重于用戶(hù)功能完整可用
- 業(yè)務(wù)高可用影響公司實(shí)際收入:比如支付流程不通
對(duì)于業(yè)務(wù)是否可用不像Crash一樣熏矿,如果發(fā)生Crash我們可以收到系統(tǒng)的回調(diào)已骇,業(yè)務(wù)不可用實(shí)際上我們是無(wú)從知道的离钝,所以針對(duì)建設(shè)移動(dòng)端業(yè)務(wù)高可用的方案總結(jié)以下幾點(diǎn):
1.數(shù)據(jù)采集
- 梳理項(xiàng)目主流程、核心路徑褪储、關(guān)鍵節(jié)點(diǎn):一般需要對(duì)項(xiàng)目主流程和核心路徑做埋點(diǎn)監(jiān)控卵渴,比如用戶(hù)下單需要從列表頁(yè)到詳情頁(yè)再到下單頁(yè),這就是一個(gè)核心路徑鲤竹,我們可以監(jiān)控具體每個(gè)頁(yè)面的到達(dá)率和下單成功率
- AOP自動(dòng)采集浪读、統(tǒng)一上報(bào):數(shù)據(jù)采集的時(shí)候可以采用AOP的方式,減少接入成本辛藻,上報(bào)的時(shí)候可以采取統(tǒng)一的上報(bào)減少流量和電量消耗碘橘,上傳到后臺(tái)之后再做詳細(xì)的分析,得出所有業(yè)務(wù)流程的轉(zhuǎn)化率吱肌,以及相應(yīng)界面的異常率
2.報(bào)警策略
- 閾值報(bào)警:比如某個(gè)業(yè)務(wù)失敗的次數(shù)超過(guò)了閾值就報(bào)警通知
- 趨勢(shì)報(bào)警:對(duì)比前一天的異常情況痘拆,如果增加的趨勢(shì)超過(guò)了一定的比例即便是未達(dá)閾值也要觸發(fā)報(bào)警
- 特定指標(biāo)報(bào)警、直接上報(bào):比如支付SDK調(diào)用失敗氮墨,這種錯(cuò)誤無(wú)需跟著統(tǒng)一的數(shù)據(jù)上報(bào)错负,出現(xiàn)立即上報(bào)
3.異常監(jiān)控
- Catch代碼塊:實(shí)際開(kāi)發(fā)中我們?yōu)榱吮苊獬绦虮罎ⅲ?jīng)常會(huì)寫(xiě)一些try{}catch(){}來(lái)捕獲相關(guān)異常,但是這樣操作完成之后,程序確實(shí)不崩潰了开缎,相應(yīng)的功能也是無(wú)法使用的斤寂,所以這些被Catch住的異常也要上報(bào),有利于分析功能不可用的原因
- 異常邏輯:比如我們需要對(duì)結(jié)果為true的調(diào)用方法進(jìn)行處理诚镰,結(jié)果為false時(shí)不執(zhí)行任務(wù)奕坟,但是我們也需要上報(bào)異常,統(tǒng)計(jì)一下出現(xiàn)這種情況的用戶(hù)的占比情況清笨,以便針對(duì)性的優(yōu)化
這里簡(jiǎn)單的舉個(gè)栗子月杉,表明意思:
try {
//業(yè)務(wù)處理
LogUtils.i("...");
}catch (Exception e){
//如果未加上統(tǒng)計(jì),就無(wú)法知道具體是什么原因?qū)е碌墓δ懿豢捎? ExceptionMonitor.monitor(Log.getStackTraceString(e));
}
boolean flag = true;
if (flag){
//正常抠艾,繼續(xù)執(zhí)行相關(guān)任務(wù)
}else {
//異常苛萎,不執(zhí)行任務(wù),這種情況產(chǎn)生的異常也應(yīng)該進(jìn)行上報(bào)
ExceptionMonitor.monitor("自定義業(yè)務(wù)失敗標(biāo)識(shí)");
}
4.單點(diǎn)追查
- 需要針對(duì)性分析的特定問(wèn)題:這些問(wèn)題相對(duì)小眾检号,很可能是和特定用戶(hù)的操作習(xí)慣腌歉、賬戶(hù)體系相關(guān),所以要盡可能獲取多的數(shù)據(jù)重點(diǎn)分析
- 全量日志回?fù)破肟粒瑢?zhuān)項(xiàng)分析:很多日志信息默認(rèn)都是只記錄不上傳翘盖,比如用戶(hù)全部的行為日志,這些日志只有在需要的時(shí)候才有用凹蜂,平時(shí)沒(méi)必要上傳馍驯,沒(méi)啥用還浪費(fèi)流量阁危,如果需要排查特定用戶(hù)的詳細(xì)信息,也可以通過(guò)服務(wù)端下發(fā)指令客戶(hù)端接收指令后上傳
5.兜底策略
當(dāng)你通過(guò)監(jiān)控了解到業(yè)務(wù)不正常之后汰瘫,請(qǐng)問(wèn)該如何修復(fù)狂打?這里就要用到兜底策略了,就是到了最后一步各種措施都做了吟吝,用戶(hù)還是出現(xiàn)了異常菱父,這種情況仍然還是要有相關(guān)聯(lián)的配置手段來(lái)達(dá)到高可用。對(duì)于業(yè)務(wù)上的異常除了熱修復(fù)的手段之外剑逃,還可以通過(guò)建立配置中心浙宜,將功能開(kāi)關(guān)關(guān)閉。
- 配置中心蛹磺,功能開(kāi)關(guān):實(shí)際項(xiàng)目中很多數(shù)據(jù)都是通過(guò)服務(wù)端動(dòng)態(tài)下發(fā)配置的粟瞬,將這些功能集合起來(lái)的處理平臺(tái)就是配置中心。舉個(gè)栗子:比如新版本上線(xiàn)了一個(gè)新功能萤捆,加了一個(gè)入口裙品,上線(xiàn)之后發(fā)現(xiàn)功能不穩(wěn)定,此時(shí)就可以通過(guò)服務(wù)端配置的方式將此功能開(kāi)關(guān)關(guān)閉俗或,這樣即使用戶(hù)無(wú)法使用新功能市怎,但是至少不會(huì)發(fā)現(xiàn)業(yè)務(wù)的異常
- 跳轉(zhuǎn)分發(fā)中心:熟悉組件化開(kāi)發(fā)的朋友都知道做組件化module的拆分必不可少的就是要有一個(gè)路由,它的作用就是跳轉(zhuǎn)分發(fā)中心辛慰,所有的跳轉(zhuǎn)都是通過(guò)路由來(lái)做区匠,如果匹配到需要跳轉(zhuǎn)到有Bug的功能界面時(shí)可以統(tǒng)一跳轉(zhuǎn)到一個(gè)異常處理的頁(yè)面
移動(dòng)端容災(zāi)方案
移動(dòng)端容災(zāi)必要性
說(shuō)到容災(zāi),首先來(lái)看一下需要防范的災(zāi)是什么帅腌?主要分為兩部分:性能異常和業(yè)務(wù)異常驰弄,只要是對(duì)用戶(hù)的實(shí)際體驗(yàn)產(chǎn)生了很大的影響,都是需要防范的App線(xiàn)上災(zāi)害速客。
- 災(zāi):性能戚篙、業(yè)務(wù)異常
傳統(tǒng)的流程是如何處理線(xiàn)上出現(xiàn)的緊急問(wèn)題的呢?傳統(tǒng)的處理流程首先需要用戶(hù)反饋出現(xiàn)的不正常情況溺职,接著開(kāi)發(fā)人員進(jìn)行緊急的BUG修復(fù)岔擂,然后重新打包上傳渠道進(jìn)行更新,可見(jiàn)傳統(tǒng)的流程比較繁瑣浪耘,靈敏度較低智亮,如果日活量較高,隨著B(niǎo)ug在線(xiàn)上存活的時(shí)間延長(zhǎng)對(duì)用戶(hù)基數(shù)的影響是巨大的点待,勢(shì)必是無(wú)法接受的
- 傳統(tǒng)流程:用戶(hù)反饋阔蛉、重新打包、渠道更新癞埠,不可接受
移動(dòng)端容災(zāi)最佳實(shí)踐
1.功能開(kāi)關(guān)
- 配置中心状原,服務(wù)端下發(fā)配置控制:首先對(duì)任何新上線(xiàn)的功能加上功能開(kāi)關(guān)聋呢,可以通過(guò)配置中心的方式下發(fā)開(kāi)關(guān)決定是否顯示新功能的入口,出現(xiàn)異常情況可以隨時(shí)關(guān)閉入口颠区,這樣可以保證上線(xiàn)的新功能處于可控狀態(tài)
- 針對(duì)場(chǎng)景削锰,功能新加或代碼改動(dòng):一是新增了功能,二是出現(xiàn)了代碼改動(dòng)毕莱,比如重構(gòu)代碼器贩,最好保留之前的老方案,在新方案上線(xiàn)之后如果有問(wèn)題朋截,可以切回之前的老方案
這里簡(jiǎn)單的做個(gè)演示:
public class ConfigManager {
public static boolean mOpenClick = true; //默認(rèn)值為true
}
mAdapter.setOnItemClickListener((view, position) -> {
//控制點(diǎn)擊事件是否開(kāi)啟
if (ConfigManager.mOpenClick){ //mOpenClick的值從接口獲取蛹稍,由服務(wù)端控制
//處理具體業(yè)務(wù)
}
});
2.統(tǒng)跳中心
組件化之后的項(xiàng)目的頁(yè)面跳轉(zhuǎn)都是通過(guò)路由來(lái)做的,如果發(fā)現(xiàn)線(xiàn)上產(chǎn)生了異常部服,可以在路由跳轉(zhuǎn)這一步攔截有Bug的跳轉(zhuǎn)唆姐,重定向到備用方案,或者統(tǒng)一的錯(cuò)誤處理中界面廓八,更多的情況是為了對(duì)線(xiàn)上用戶(hù)產(chǎn)生的影響降到最低奉芦,如果有Bug不能進(jìn)行熱修復(fù),也沒(méi)有合適的開(kāi)關(guān)可用剧蹂,會(huì)做一個(gè)臨時(shí)的H5頁(yè)面声功,讓用戶(hù)點(diǎn)擊之后跳轉(zhuǎn)到臨時(shí)的H5頁(yè)面,這樣用戶(hù)還是可以操作宠叼,只是在體驗(yàn)上稍微差一點(diǎn)减噪,總歸來(lái)說(shuō)比不能用強(qiáng)的多
- 界面切換通過(guò)路由,路由決定是否重定向
- Native Bug不能熱修則跳轉(zhuǎn)到臨時(shí)H5
3.動(dòng)態(tài)化修復(fù)
目前為止车吹,國(guó)內(nèi)市場(chǎng)安卓的熱修復(fù)方案已經(jīng)比較成熟了,對(duì)于大型項(xiàng)目來(lái)說(shuō)醋闭,一般都會(huì)支持熱修復(fù)的能力窄驹,熱修復(fù)技術(shù)就是用戶(hù)不需要重新安裝一個(gè)Apk,就可以實(shí)現(xiàn)比原有Apk有較大更新的能力证逻,比如微信的Tinker和美團(tuán)的Robust都是非常好的熱修復(fù)實(shí)現(xiàn)方案乐埠。需要注意的是,熱修復(fù)也只是一個(gè)功能囚企,對(duì)于熱修復(fù)也需要加上各種完善的統(tǒng)計(jì)丈咐,需要知道熱修方案是否真正有效果,沒(méi)有用造成更大的損失
- 熱修復(fù)能力龙宏,可監(jiān)控棵逊、灰度、回滾银酗、清除
- 推拉結(jié)合辆影、多場(chǎng)景調(diào)用保證到達(dá)率
- Weex徒像、RN增量更新
4.安全模式
安全模式側(cè)重于移動(dòng)端發(fā)生嚴(yán)重Crash時(shí)的自動(dòng)恢復(fù),做的好的安全模式往往會(huì)有幾級(jí)不同的策略蛙讥,比如App多次啟動(dòng)失敗锯蛀,那就重置整個(gè)App到安裝的狀態(tài),避免因?yàn)橐恍┡K數(shù)據(jù)導(dǎo)致的App持續(xù)閃退次慢,同時(shí)如果有Bug并且非常嚴(yán)重到了最嚴(yán)重的等級(jí)旁涤,可以采用阻塞性熱修來(lái)解決,即:必須等熱修成功之后才可進(jìn)入主頁(yè)面迫像。需要注意的是劈愚,安全模式不僅僅可以針對(duì)App Crash,也可以針對(duì)一些組件侵蒙,比如網(wǎng)絡(luò)請(qǐng)求多次失敗后也可以進(jìn)入安全模式造虎,暫時(shí)拒絕用戶(hù)的網(wǎng)絡(luò)請(qǐng)求,避免給服務(wù)端造成的額外壓力
- 根據(jù)Crash信息自動(dòng)恢復(fù)纷闺,多次啟動(dòng)失敗重置App
- 嚴(yán)重Bug可阻塞性熱修復(fù)
- 異常熔斷:多次請(qǐng)求失敗則主動(dòng)拒絕
容災(zāi)方案總結(jié):
這幾種方式是由簡(jiǎn)單到復(fù)雜的遞進(jìn)算凿,為了保障線(xiàn)上的穩(wěn)定性,最好在應(yīng)用中多加入幾個(gè)穩(wěn)定性保障方案犁功。
穩(wěn)定性長(zhǎng)效治理
對(duì)于穩(wěn)定性?xún)?yōu)化來(lái)說(shuō)是一個(gè)細(xì)活氓轰,需要打持久戰(zhàn),不能一個(gè)版本優(yōu)化了浸卦,后面又惡化了署鸡,因此需要在項(xiàng)目開(kāi)發(fā)的整個(gè)周期內(nèi)的不同階段都加上相應(yīng)的方案。
1.開(kāi)發(fā)階段
在開(kāi)發(fā)階段組內(nèi)每個(gè)開(kāi)發(fā)人員的編碼實(shí)力都是不一樣的限嫌,因此需要統(tǒng)一編碼規(guī)范靴庆,然后結(jié)合一些手段增強(qiáng)人員的編碼功底,盡可能的將問(wèn)題消滅在編碼階段怒医,盡可能的寫(xiě)出高質(zhì)量的代碼炉抒,同時(shí)要結(jié)合開(kāi)發(fā)階段的技術(shù)評(píng)審,以及每天的互相CodeReview機(jī)制稚叹,堅(jiān)持幾個(gè)月編碼水平肯定會(huì)有明顯的提升焰薄,開(kāi)發(fā)階段明顯的問(wèn)題應(yīng)該就不會(huì)再有了,而且代碼風(fēng)格結(jié)構(gòu)也會(huì)大體一致扒袖。同時(shí)開(kāi)發(fā)階段還需要做的事情就是架構(gòu)優(yōu)化塞茅,項(xiàng)目的架構(gòu)應(yīng)該根據(jù)項(xiàng)目的不同發(fā)展階段來(lái)不斷優(yōu)化,這里說(shuō)兩點(diǎn)季率,第一能力收斂比如界面切換的能力用路由來(lái)實(shí)現(xiàn)野瘦,對(duì)網(wǎng)絡(luò)請(qǐng)求要統(tǒng)一網(wǎng)絡(luò)庫(kù)統(tǒng)一使用方式,這樣可以避免不正當(dāng)?shù)氖褂脦?lái)的Bug飒泻,第二統(tǒng)一容錯(cuò)缅刽,比如對(duì)于網(wǎng)絡(luò)請(qǐng)求來(lái)說(shuō)可以在網(wǎng)絡(luò)請(qǐng)求回來(lái)的時(shí)候加上預(yù)先校驗(yàn)啊掏,判斷回來(lái)的數(shù)據(jù)是否合法,如果不合法就不需要再把數(shù)據(jù)轉(zhuǎn)給上層業(yè)務(wù)了
- 統(tǒng)一編碼規(guī)范衰猛、增強(qiáng)編碼功底迟蜜、技術(shù)評(píng)審、CodeReview機(jī)制
- 架構(gòu)優(yōu)化:能力收斂啡省、統(tǒng)一容錯(cuò)
2.測(cè)試階段
- 功能測(cè)試娜睛、自動(dòng)化測(cè)試、回歸測(cè)試卦睹、覆蓋安裝
- 特殊場(chǎng)景畦戒、機(jī)型等邊界測(cè)試
- 云測(cè)平臺(tái):輔助測(cè)試,滿(mǎn)足對(duì)特殊機(jī)型的測(cè)試需求
3.合碼階段
開(kāi)發(fā)時(shí)肯定是在自己的分支進(jìn)行開(kāi)發(fā)结序,測(cè)試通過(guò)之后才會(huì)往主干分支合入障斋,合入之前首先需要進(jìn)行代碼的編譯檢查和靜態(tài)掃描發(fā)現(xiàn)可能存在的問(wèn)題,經(jīng)過(guò)校驗(yàn)之后也不能直接合入徐鹤,應(yīng)該將自己的分支首先合入到一個(gè)和主干分支一樣的分支中進(jìn)行預(yù)編譯垃环,編譯通過(guò)之后最好加上主流程的回歸測(cè)試
- 編譯檢測(cè),靜態(tài)掃描
- 預(yù)編譯流程返敬、主流程自動(dòng)回歸
4.發(fā)布階段
到了發(fā)布階段一般來(lái)說(shuō)App都是經(jīng)過(guò)了開(kāi)發(fā)自測(cè)遂庄、QA測(cè)試、內(nèi)部測(cè)試等測(cè)試環(huán)節(jié)劲赠,相對(duì)來(lái)說(shuō)比較穩(wěn)定了涛目,但是需要注意的是,很多問(wèn)題你不可能全部測(cè)出來(lái)凛澎,所以必須謹(jǐn)慎對(duì)待
- 多輪灰度:灰度的量級(jí)要由小變多霹肝,爭(zhēng)取以最小的代價(jià)暴露最多的問(wèn)題
- 分場(chǎng)景、維度全面覆蓋
5.運(yùn)維階段
任何一個(gè)小問(wèn)題在海量用戶(hù)面前都會(huì)影響巨大塑煎,因此這個(gè)階段必須要依靠APM的靈敏監(jiān)控
- APM靈敏監(jiān)控
- 回滾沫换、降級(jí)策略
- 熱修復(fù)、容災(zāi)方案
如果你覺(jué)得這篇內(nèi)容對(duì)你還蠻有幫助轧叽,我想邀請(qǐng)你幫我三個(gè)小忙: 點(diǎn)贊,轉(zhuǎn)發(fā)刊棕,有你們的 『點(diǎn)贊和評(píng)論』炭晒,才是我創(chuàng)造的動(dòng)力。
性能系列專(zhuān)欄其他文章
關(guān)于 Android內(nèi)存優(yōu)化你應(yīng)該了解的知識(shí)點(diǎn)
關(guān)于 Android啟動(dòng)優(yōu)化你應(yīng)該了解的知識(shí)點(diǎn)
Android卡頓優(yōu)化分析及解決方案甥角,全面掌握
關(guān)于Android UI繪制優(yōu)化你應(yīng)該了解的知識(shí)點(diǎn)