前端可用性保障實踐

美團雲發表於2019-02-23
  • 本文轉自美團點評技術學院,未經作者許可,不允許私自轉載。
  • 美團雲知乎機構賬號每日分享雲端計算產品,技術內容。 歡迎關注!
  • 加入美團雲技術交流群(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)

其優化的核心內容就是把儘可能多的首幀渲染所需資訊在第一個請求的響應中給出,也就是主文件請求,讓使用者能夠儘可能快的看到內容。

從優化效果上來講,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劫持狀況等。

作者簡介

禹霖,美團點評前端技術專家,負責金融錢包及支付前端團隊。

相關文章