- 本文轉自美團點評技術學院,未經做者許可,不容許私自轉載。
- 美團雲知乎機構帳號每日分享雲計算產品,技術內容。 歡迎關注!
- 加入美團雲技術交流羣(QQ羣:469243579),每日分享更多精彩技術文章。
如何定義前端服務可用性
通常可用性都是說後端服務的可用性,都說咱們的服務可用性到了幾個9,不多有人把可用性放到前端來。其實對於任何一個有UI交互流程的業務,都會有前端服務可用性,後端的可用性作的再高,前端一個按鈕寫的有問題點擊不起做用也會致使用戶沒法完成流程。
前端服務可用性包含三個部分:
- 前端代碼可用性(測試質量,線上異常)。
- 靜態資源服務可用性。
- 網絡鏈路可用性(DNS劫持、網絡性能)。
既從業務後臺服務往上,一直到用戶界面,一切都是前端服務,這裏面一切用戶可能遇到的問題都是前端可用性的範疇。
這就是咱們認爲的前端可用性,收銀臺的可用性建設就是圍繞着這三個部分展開的。
如何衡量前端服務可用性
前端服務的可用性衡量和後端的衡量方法相相似,不考慮影響範圍大小,只考慮存在故障的時常,最大化考量可用性。可用性指標不是爲了讓咱們經過複雜的算法來減少事故對可用性計算的影響,而是爲了激勵咱們在可觀測範圍內作到沒有問題,越作越好。影響用戶數、影響訂單數、影響GMV等指標更多的是用於作事故定級。
哪裏容易出問題
前端代碼可用性:
- 空指針問題是困擾前端的一個大問題,因爲JS自己是弱類型動態語言,沒法在開發及編譯過程當中經過工具推導出可能出現問題的點,進而在前端研發過程當中很容易疏忽形成空指針問題;
- 業務邏輯覆蓋率,指的是在業務項目當中,代碼對動態邏輯的處理能力,每每在一些複雜的業務項目當中,邏輯混亂交錯,前端的展現和進一步的動做由後端控制,這種狀況下複雜的邏輯交織在一塊兒產生無數分支,邏輯環境難以模擬,進而很容易在邏輯的處理上產生疏忽;
- 兼容性,問題困擾着各個端的研發,對於前端來講,要面臨的環境更多,包括平臺、系統版本、瀏覽器版本、WebView版本、Hybrid橋版本等等,很難從測試角度所有覆蓋。
靜態資源服務可用性:
- 前端靜態資源服務鏈的穩定性,例如NGINX、Node等等;
- CDN並非任什麼時候候均可以正常提供服務的,可能會遇到SSL證書鏈問題、回源服務可用性問題等等。
網絡鏈路穩定性:
- DNS劫持是一個老大難問題,大部分狀況下是運營商爲了節省跨省流量結算的費用而進行DNS劫持,走內部的緩存,還有一部分狀況是廣告,想象一下把收銀臺的代碼劫持並插入一個運營商廣告是有多可怕。
大塊的問題就是上述幾種,細枝末節的問題就不在這裏一一細表,那麼具體咱們是怎麼解決的呢?
怎樣保障才能使人信服?
記得剛剛開始負責支付業務的時候,老闆(rank)常常問一個問題:「收銀臺穩定性怎麼保障?」,我當時想的就比較簡單,無非就是流程保障、測試保障等等,但這不是老闆想聽的,否則他也不會老問我,顯然是當時沒有回答出他想要的答案。如今想一想真是「too young too simple, some times naive」。
在美團點評,收銀臺是一個橫向的業務基礎服務,是全部業務的閉環環節,全部線上業務交易的最終環節所有由收銀臺來完成,它的重要性不言而喻。對於收銀臺來講,有三點須要保障,這三點分別是可用性、體驗和安全,它們共同爲一個指標服務,那就是「支付成功率」。其中,對支付成功率影響最大的就是可用性。
可用性對支付成功率的影響有多大?
一個小小的bug上線後即便及時發現並回滾,可能也會形成幾百上千萬營業額的損失,這對整個團隊來講都是沒法接受的。因此,對於收銀臺來講,保障可用性是第一優先級。
同時,支付做爲一個特殊的業務有它對可用性獨到的要求,在可用性保障上必然不是任何業務都會用到的那老幾樣兒。老闆想聽的是對穩定性保障的獨到看法,可複製的方法,有可用性保障的理論基礎,讓任何一個往後負責這個業務的人都可以照方抓藥,保障前端服務的穩定性。
如今總結起來可用性的保障分爲三個階段:
保障手段分爲三個大類:
「軟的」是指用「人」來保障的部分:
……
「硬的」是指用「工程工具」來保障的部分:
- 靜態代碼檢查
- 單測
- Web自動化測試
- 持續集成
- 線上前端異常監控
- 業務異常監控
- 前端服務異常監控
- 網絡異常監控
「根源的」是整個可用性保障的核心,是指經過「技術選型」來讓系統更健壯,這裏面有兩個核心點。
技術選型要簡單穩健
要求在具有伸縮性的基礎下避免任何複雜的不可控技術方案。核心鏈路上的全部代碼,團隊要具有維護能力,要減小外部依賴。
這裏面有一個關鍵的選型概念就是「場景契合度」,技術選型不是你願意用什麼,你熟悉用什麼,是在這個業務場景和團隊規模下須要你用什麼。
舉個例子,收銀臺是一個單頁應用,之因此設計成單頁應用是由於它涉及到的視圖跳轉和數據傳遞太多,單頁應用相比多頁更具優點。那麼在選型的時候咱們當時有React、Angular、Ember等一線前端SPA框架能夠選,但最後咱們仍是本身作了一個簡單的視圖生命週期管理工具,爲何?
「場景契合度」,React和Angular等前端框架更適合極端複雜的大型單頁應用,爲了可以更好的處理這種複雜度採用了一系列厚重的工具去約束研發的過程,其中還包含一些這個項目不會遇到問題的優化,例如渲染優化等等。對於收銀臺來說,單個視圖中的複雜度並無那麼高,能夠遇到前端渲染性能瓶頸的項目並很少。
「源碼維護能力」,收銀臺做爲核心鏈路中的核心業務,在技術上絕對不容許被動,團隊必須具備核心代碼的維護能力。而依照咱們當時的團隊規模,這是不現實的。
在收銀臺這個SPA場景裏,咱們只須要視圖生命週期管理這個功能。因此,咱們參考Cocoa View Controller的生命週期設計實現了一個簡單的單頁視圖工具「Cyra」,它只負責視圖生命週期的管理,簡單、拓展性高、源碼可維護且無外部依賴。
避免出現核心鏈路上的可用性短板
舉個例子,網頁首幀渲染優化有三種常見方式:
其優化的核心內容就是把儘量多的首幀渲染所需信息在第一個請求的響應中給出,也就是主文檔請求,讓用戶可以儘量快的看到內容。
從優化效果上來說,SSR的效果最好,它能夠把JavaScript(如下簡稱「JS」)、CSS、HTML之外的動態的數據一塊兒經過第一個響應返回回來。
可是,最後咱們選擇的是編譯預渲染,爲何?
先說什麼是SSR。這個概念是新提出來的,但原理很早就存在,相似JSP、ASP這種技術早年間一直都是SSR,在服務器端把頁面拼裝好傳遞給客戶端。和佛家的人生三境界同樣,禪中徹悟後又回去了,就像如今的前端服務化很難作到當年微軟ASP.NET Web Form那個水平。
後來前端行業發展迅速,發生了兩個大的變化:
你們開始作先後端分離,把靜態資源單獨管理,好處就不說了,有一個弊端就是當用戶瀏覽器把靜態資源下載下來後可能還須要另一個請求去獲取這個頁面上的動態數據;
前端工程化的興起,你們會把CSS JS HTML結構統一打包到一個JS文件中,HTML中只有JS的引用,這樣就致使HTML下載完成後仍是白屏,只有等到這個巨型JS下載完成後首幀內容纔開始渲染。
這時就用到了SSR,通用作法是增長一個Node層,在服務器端作首屏內容的拼接,包含靜態數據,這樣可以保障首幀渲染不只快,還包含首屏所須要的數據。
能夠看到,Node這一層在咱們界面請求的核心鏈路上,Node自己的可用性和上下游的服務相比要差不少,其自身的穩定性須要許多其餘工具去保障,那麼對於這塊業務來講,Node這一層成爲了「核心鏈路上的可用性短板」,這樣即便背後的各個後端系統可用性再好,只要Node這一層掛掉就會形成用戶沒法訪問的問題。
因此基於「避免出現核心鏈路上的可用性短板」這一層考量,咱們退而求其次選用「編譯預渲染」,在編譯期間把首屏結構所有拼裝好,這樣可用性就獲得了保障。
關於Node在服務端的應用上,我認爲其實大多數狀況下,不用要比用要可貴多,關於這方面的一些思考能夠詳見後續文章《服務端爲何不能用Node》。
理論有了,咱們是怎麼作的?
「軟的」流程規範部分就不展開講了,各個團隊都差很少,只不過是完善不完善的差別。接下來主要講一下「硬的」部分。
前文提到,「硬的」保障主要指的是工程工具的保障手段,工程工具不少,這裏對應前文幾大問題的順序,講一講咱們的解決方案。
前端代碼可用性部分主要有三個容易出問題的點:空指針、業務邏輯覆蓋率、兼容性。
空指針
「空指針」部分的問題解決只能從語言自己來解決,JS自己是弱類型動態語言,沒法在開發及編譯過程當中經過工具推導出可能出現問題的點。針對這一點咱們從2015年開始實踐TypeScript(如下簡稱「TS」),當時也看了Facebook的Flow,但當時Flow還不夠成熟,因此沒有選用。
引入TS後,將咱們的弱類型語言變成強類型語言,從編碼過程當中就能夠幫助過濾掉很大一部分空指針問題,TS強大的類型推導系統能夠幫咱們分析出系統中的空指針隱患,進而能夠解決線上99%的空指針問題。固然TS還有不少其餘好處,這裏就不展開了。
業務邏輯覆蓋率
「業務邏輯覆蓋率」這個問題的背景再也不贅述,因爲收銀臺的複雜度高、case多,複雜狀況下的後端狀態很難模擬,所以只能採用自動化工具去解決,這就涉及到了「Web自動化流程測試」。
Web自動化流程測試在這種場景下除了能夠驗證case的正確性之外,最重要的功能就是要有一個異常強大的case管理模塊。業界目前並無理想的工具可以支撐咱們的場景。
美團點評內部有一個咱們參與需求的Web自動化流程測試工具「Freekite」,它在case驗證功能的基礎上,有一個強大的可視化case管理模塊,支持複雜的case細分。除了界面操做的細分外,能夠全量Mock或部分Mock後端的數據響應,根據響應拆分出不一樣的case分支。除此以外,還包含智能自動化斷言功能,斷言基本不須要人工參與。
可能有人要問了,這個case錄完之後萬一遇到界面改版怎麼辦?不要緊,雖然有強大的類似度匹配功能,Freekite還支持單獨節點的從新錄製,也就完美的解決了case的維護問題,大幅度減小工做量加強效率。緊接着咱們會在項目中增長Freekite的持續集成,在項目的每個階段進行流程上的自動化迴歸驗證,業務邏輯覆蓋率的問題就基本解決了。下圖爲Freekite可視化Case管理。
兼容性
「兼容性」問題公司內部有云測平臺,能夠快速在多機型真機上回歸主要流程,能夠經過雲測平臺覆蓋佔有率95%以上的各類機型。然而兼容性也是同樣,須要從根本上選用一個可靠的選型,從而避免在處理兼容性問題上會遇到的拆東牆補西牆最後仍是不放心的尷尬境地。兼容性問題在移動端除了佈局外主要出如今兩種操做中:點擊和滾動。
前文描述的自主研發的單頁視圖工具就以最簡單的div隱藏顯示的方式來處理視圖切換,使全部元素處於正常的文檔流當中,點擊處理也經過分級降級的方式最大化平衡體驗和兼容性,從而保障了整個項目的兼容性。
靜態資源服務可用性主要就是NGINX層的健康檢查及CDN的回源監控,這一點公司SRE有強大的系統支持(有關美團點評SRE的實踐能夠參考以前的博客文章),這裏就很少講了。
網絡可用性上最頭痛的問題是DNS劫持,前文講到了DNS劫持方面除了惡意劫持之外,主要是運營商以節省跨省流量結算費用爲目標進行DNS劫持。當運營商系統發現HTTP訪問的域名時會在區域內的服務器中緩存一份資源,後續用戶再請求的時候其域名解析會被解析到運營商的服務器上去由運營商的服務器直接返回內容。
其應對方法只有使用HTTPS,但並不只僅是在原有的域名HTTP的基礎上切換HTTPS那麼簡單,還須要保障這個域名不支持HTTP訪問而且沒有被大範圍使用HTTP訪問過。若是不這樣作的話會出現一個問題,運營商在DNS解析的時候並不知道這個域名是用什麼協議訪問的,當以前已經記錄過這個域名支持HTTP訪問後,無論後續是不是HTTPS訪問,都會進行DNS劫持。這時若是使用的是HTTPS訪問,會由於運營商的緩存服務器沒有對應的SSL證書而致使請求沒法創建連接,從而遇到請求失敗的問題。在以前業務切換HTTPS的時候就遇到了這個問題,請求成功率從99.96%下降到了96%,花了大量的時間去定位問題。當切換了全新的域名後這個問題才獲得瞭解決。
在過後方面,除了強大的支付後臺業務系統監控外,公司還有完善的通用監控系統,例如異常監控系統能夠分級分批上報前端的JS Error及自定義異常,性能監控系統Performance能夠了解前端的訪問狀況作性能分析,網絡監控系統CAT能夠快速定位網絡層性能情況、區域DNS劫持情況等。
做者簡介
禹霖,美團點評前端技術專家,負責金融錢包及支付前端團隊。