GMTC 大前端時代前端監控的最佳實踐
時間: 2018-07-04來源:OSCHINA
前景提要
摘要: 今天我分享的內容分成三個部分: 第一部分是“大前端時代前端監控新的變化”, 講述這些年來,前端監控一些新的視角以及最前沿的一些思考。 第二部分"前端監控的最佳實踐", 從使用的角度出發,介紹前端監控系統的各種使用姿勢 最后是“阿里云ARMS前端監控系統架構”, 簡單地剖析下,阿里云前端監控系統是怎么實現的。 本文來自阿里云前端監控團隊,轉載請注明出處
本文為2018年6月21日,在北京舉辦的GMTC(全球大前端技術大會),下午性能與監控專場,由阿里云前端監控團隊前端技術專家彭偉春帶來的演講稿,現場反饋效果非常好,地上都坐了三圈,很多人反饋根本無法擠進去。先上現場照。

正文從這里開始~

大家下午好,今天我給大家帶來的主題是《大前端時代前端監控的最佳實踐》。

先做一個自我介紹,我叫彭偉春,英文名是Holden, 阿里花名是六猴, 大家都叫我猴哥。是阿里開源同構框架beidou的作者,目前是阿里云前端系統技術負責人。

今天我分享的內容分成三個部分: 第一部分是“大前端時代前端監控新的變化”, 講述這些年來,前端監控一些新的視角以及最前沿的一些思考。 第二部分"前端監控的最佳實踐", 從使用的角度出發,介紹前端監控系統的各種使用姿勢。 最后是“阿里云ARMS前端監控系統架構”, 簡單地剖析下,阿里云前端監控系統是怎么實現的。


先進入我們第一個環節 大前端時代前端監控新的變化。
要了解前端監控新的變化,還得先看看前端這些年發生了哪些變化: 首先是Gmail的橫空出世,開啟了SPA的時代 Backbone/Angular等框架帶來了MVVM模式的同時,也把JS從腳本語言提升到了工程語言 React Native/Weex把移動端開發從Hybrid模式進化到了跨端開發模式 Node.js問世為前端帶來了更多的可能性

前端這些年發生了翻天覆地的變化,又會給監控帶來什么呢?讓我們思考下以下幾個問題: 傳統監控模式能否適用于新的技術?比如PV統計 SPA模式下首屏如何計算? 跨端開發給監控帶來什么什么挑戰? 前端監控的上報模式在Node.js端是否合理?
接下來我和大家一起探討其中的一兩項

早些年,SPA如此盛行,我們也在業務中做了嘗試,體驗是大幅提升了,可業務方卻吐槽PV下降了。

那到底是什么導致了PV下降了呢?在后端直出時代,我們每一次的交互,都是向后端請求一個新的頁面,PV自然就高,改成SPA模式之后,大量的頁面請求變成了頁內路由,或者說是頁內轉場。那如何解呢?這難不倒我們,大部分框架路由都是基于哈希實現的,我們只要偵聽hash改變,每次改變上報一次PV就好了。也有少量的路由并不是基于哈希實現的,比如angular, 這時候就需要輕量級地hack pushState和replaceState。

這樣就完美了嗎?

我們再思考下以下幾個案例 某新聞類的網站,每次看完之后,都會下拉刷新,加載新的內容,這個時候是算一次PV還是多次? 天貓商品列表頁,看完一屏之后,向上滾動會再加載新的一屏,PV該算一次還是多次? 阿里云郵后臺一直開著,每周上百次查看,是算一個PV還是每次查看都計算一次? 未關閉的瀏覽器tab幾小時之后再次瀏覽,該不該再計一次PV? 查找信息時,瀏覽器Tab之間快速切換,切換過程中要不要計一次PV?
其實還有很多其它層出不窮的場景,具體該如何去統計PV留給大家去思考, 不再展開。

接下來我們探討一個大家最感興趣的話題: 性能。先看一組我們的統計數據,淘寶旺鋪頁面點擊率隨加載時間變長從85%的點擊率逐步降低到了82%,別小看這3%,在阿里這么大的體量下,3%意味著巨大的商業價值,那站在前端監控的角度,首屏是如何統計出來的呢?

回到那個刀耕火種的年代,那時候要什么沒什么,都是自己動手豐衣足食。這就是手動打點階段: 手動打點,分別在頁頭和首屏dom節點處new Date()打點,計算差值,作為首屏時間,再加上setTimeout(new Date(), 0)標記首屏可交互時間。

隨著前端的飛速發展,手工打點的模式早已滿足不了需求了。為了幫助開發人員更好地衡量和改進web性能,W3C性能小組引入了 Navigation Timing API 幫我們自動,精準的實現了性能測試的打點問題,大致地過一下,性能API里面包含了【卸載上一個頁面】【重定向】【應用緩存】【DNS域名解析】【TCP連接】【請求頁面】【響應】【頁面處理】最后觸發load事件,通常我們把domContentLoaded作為首屏時間。Chrome最早支持,IE跟進。

在很長一段時間里,我們都享受著performance API帶來的便利, 但隨著SPA模式的盛行,我們再回過頭來看看W3C標準是否足夠了。先來看一個案例,這是阿里云某產品的管理后臺。整個加載過程分成三個部分,1. 加載初始的空殼頁面 2.加載JS資源并異步請求數據 3. 前端渲染中間的主體部分。按照W3C標準取值首屏時間應該是1106ms, 而實際的首屏在1976ms,也就是完成異步取數據后渲染完頁面的時間點。為什么會相差如此大呢?實際上SPA的盛行讓W3C標準失去了原來的意義。

針對這種情況Google lighthouse提出了FMP的概念,first meaning paint, 也就是主要內容可見時間,那什么是主要內容? 每個人得出的結論可能會不一樣。

先做一個猜想:主要內容 = 頁面渲染過中元素增量最大的點。

先通過飛豬案例做一次驗證。

猜想成立。

再通過手淘案例做一次驗證。

猜想不成立。

那到底是什么原因導致我們的猜想不成立? 首先是元素是否可見, 不可見的元素對用戶的影響基本為0。 其次是每個元素對頁面的影響是否等效?由此引出權重,不同的元素采用不同的權重計算影響。阿里云前端監控

根據上面的修正因子。我們重新設計了一遍算法, 計算每次變化的得分,一起來看看,算法是如何實現的?
如圖所示分為三個步驟 偵聽頁面元素的變化; 遍歷每次新增的元素,并計算這些元素的得分總; 如果元素可見,得分為 1 * weight(權重), 如果元素不可見,得分為0;
如果每次都去遍歷新增元素并計算是否可見是非常消耗性能的。實際上采用的是深度優先算法,如果子元素可見,那父元素可見,不再計算。 同樣的,如果最后一個元素可見,那前面的兄弟元素也可見。通過深度優先算法,性能有了大幅的提升。

再拿之前的手淘案例來驗證一遍。

經過改良之后,第三屏主要內容的得分是最高的,符合預期。

那么接下來首屏統計又會發生什么樣的變化呢?其實統計首屏時間本身就是瀏覽器的職責,交由瀏覽器來處理是最好的。目前W3C關于首屏統計已經進入了提議階段,坐等W3C再次標準化。大家可以在github上看到最新進。
限于篇幅,前端監控其它新的變化不再展開。講了這么多前端監控的新變化,那什么才是打開前端監控最最正確地姿勢呢?

由此進入我們的第二個環節,“前端監控的最佳實踐”。

我用一個表達式“要是什么什么就好了”來總結。我經常會想【要是天上能掉錢就好了】,【要是有個機器人幫我寫代碼就好了】。同樣的,每次發版之后都是提醒吊膽的,不知道用戶到底能不能正常使用。(這時候你就會想)要是能有雙眼睛幫我盯著系統就好了;每次出錯,都是用戶投訴反饋問題,實際等到用戶主動反饋問題,影響面已經非常大了: (這時候你就會想)要是能在第一時間發現錯誤就好了;

還真有這樣的案例,前年雙十一凌晨值班,突然收到郵件和短信告警,于是點開了詳情。

發現在接口成功率趨勢圖中,接口請求量大幅上升,伴隨著成功率急劇下降,再查看錯誤信息聚合模塊,發現頻率最高的錯誤信息是【交易規則沖突】,深度排查之后,最終找出了原因,是運營配置的雙十一優惠規則和平時優惠規則產生了沖突,導致下單失敗。最后凌晨4點申請了緊急發布修復了沖突,解除告警。

由此可以得出最佳實踐之一:主動監控。當然主動監控的內容不僅局限于API成功率,也包括JS錯誤率等。稍微總結下流程:先是配置告警規則; 然后就可以放心大膽地睡覺了,如有任何風吹草動,系統馬上會通知到我們,再通過錯誤聚類模塊,精準地定位問題。再手起刀落,bug修復完成。

再回到我們的【要是什么什么就好了】,在做性能優化的時候,有時候明明整體性能已經不錯了,可偏偏有少量用戶覺得很慢:(這時候你就會想)要是能知道慢速用戶發生了什么就好了。

這時候我們就需要用到【性能樣本分布】,打開頁面性能頁面,查看0 -60秒之間每個區間的性能樣本分布情況,從分布圖中可以看出來大部分用戶加載時間都在2秒以內,極少數部分用戶的頁面時間在10秒左右的。
拖動下面的滑塊,縮小時間范圍到10S左右,這時候系統就會篩選出10秒左右的慢會話。

點擊展開某次慢會話,不僅可以看到這次慢會話的基本信息,比如網絡類型等,還可以看到完整的資源加載瀑布圖,可以清晰地看出來,具體是什么資源導致整個會話變慢。由此我們又可以得出最佳實踐之二:慢會話追蹤

再回到我們的【要是什么什么就好了】,有時候用戶提交了一條反饋,某某功能出錯用不了,這時候你又不知道用戶端到底報了什么錯,是不是又得打電話給用戶,還得手把手教用戶如何通過瀏覽器開發者工具把錯誤截圖下來發你。我哩個去,用戶這個時候很可能因為系統太爛了,已經不堪其辱,早就把頁面關了并且發誓再也不用這破系統。(這時候你就會想)要是能知道用戶報了什么錯就好了。

別怕,打開阿里云前端監控的【訪問明細】搜索用戶ID,直接可以看到該用戶在訪問過程中,到底報了什么錯。

有時候拿到了用戶報錯時的基本信息,也知道用戶報了什么錯,但是在自己電腦上調試的時候,無論如何也復現不了,這個時候是不是又得去和用戶溝通,讓用戶描述重現路徑,實際上用戶可能自己都忘了具體怎么做才能重現錯誤。(這時候我們就會想)要是能重現用戶行為就好了。

【視頻演示】我們現場來模擬一次用戶出錯還原,左邊是用戶實際操作的屏幕,為了更好地展示效果,我把用戶行為實時地展示在右邊的屏幕上:
第一步: 模擬用戶在淘寶頁面上做出了一系列的操作, 鼠標移動、滾動頁面,搜索等;
第二步:假設突然出現了某某錯誤,這時系統會把記錄的用戶行為存儲到服務端;
第三步: 開發人員通過會話ID查詢到出錯行為,最終進行還原。大家可以看到左邊屏幕不再操作,右邊屏幕還原出了之前出錯的所有行為。

大家一定在想這么炫酷的能力是如何實現的呢?接下來就為大家揭秘阿里云前端監控系統背后的技術架構。

就從大家最感興趣的錯誤還原講起,大家可能在猜測,是不是把整個頁面錄制成視頻了。其實不是這樣的,視頻太大了,不可能出錯了把一個視頻發到服務端,這樣是對用戶資源的嚴重浪費。先看示意圖(跟著箭頭從左到右): 首先,每一次會話都有一個唯一的session ID,這是串聯起所有行為的紐帶。 其次,用戶行為又分成兩個部分,其一是用戶的操作,比如鼠標滑動,點擊,頁面滾動等,其二是頁面的變化。這兩者我們都統稱為用戶行為,記錄在同一個隊列中。 一開始的時候,系統會記錄下初始的頁面作為第一幀,這是唯一的一次完整頁面記錄。 針對用戶操作,我們會記錄事件的類型,鼠標位置等關鍵信息,保存到隊列中。 針對頁面變動,我們會起一個mutationObserve偵聽頁面的改動,每次只記錄改動的部分,保存到隊列中。 無論是事件還是頁面改動,都是對等的一幀,每一幀都會有當前時間,與上一幀間隔時間等基本信息用戶還原。 一旦出錯,SDK就把隊列發送到監控系統,并清空當前隊列。 還原端根據記錄的行為隊列,根據時間逐一播放出來。最終形成一個類似于視頻的效果。

大家可能覺得還不過癮,接下來為大家講一下阿里云ARMS前端監控系統的整體架構。
首先從左到右分成三個域。分別是日志采集域,日志分析域和監控告警域。在日志采集域,客戶端通過SDK將信息上報到Nginx服務器, 日志服務SLS在Nginx服務器上起一個agent,去把日志信息同步過去,日志到了SLS就相當于到了一個大的蓄水池。再通過實時計算引擎的計算,結果部分存儲到HBase,另一部分結果回存到SLS日志服務用于搜索。
最終通過restful API向前端提供數據,前端渲染出數據dashboard.
是不是感覺很簡單地樣子,有句話叫做【看山跑死馬】,山看起來就在眼前, 可就算騎馬過去馬都會累死。那就讓我們一起來揭開它的神秘面紗吧。

接下來重點介紹跟前端同學工作密切相關的日志采集域,相比業界,我們的日志采集還是有很多可圈可點之處的。比如說: 靜默采集: 只需要一行代碼接入SDK就行了,所有的API請求、資源加載、JS錯誤、性能等都自動監控起來了。省去了繁瑣的配置。 單元測試 +
自動化測試:前端監控的目的就是去監控前端的異常情況,不給頁面帶來新的異常這是我們的底線,對此,我們有完善的單元測試和自動化測試去保障SDK本身的質量。 (SDK出錯隔離):但實際上任何系統都不能保證自己不會出錯,那么萬一SDK本身報錯了,我們還有異常隔離機制,確保出錯也不會影響業務的運行。

這些內容我都不詳細展開,那接下來我重點講一下,阿里云前端監控是如何突破局限優雅地上報日志
大家都知道,http徵求意見稿rfc2616規定瀏覽器對于一個域名,同時只能有 2 個連接。而PV、UV、ajax請求、JS邏輯錯誤、頁面資源加載等等都會觸發上報,同時2個連接明顯不夠用,可能會造成網絡阻塞,上報延遲
后來在修正稿rfc7230中去掉了這個限制, 只規定了限制數量,但并未指定具體數字,瀏覽器也實際放寬了限制。比如Chrome是同時6個連接。
然而,一個請求獨占一個連接,有時候6個連接也是不夠用的
大家可能會想, 那既然規范都沒有指定要限制多少條,那瀏覽器為什么還要限制6條呢?其實也是出于公平和安全考慮,如果不限制數量,理論上一個客戶端就能占用大量服務器資源,甚至壓垮服務器。

那如何突破限制呢?有一個絕招:就是升級到http2, 利用h2的多路復用特性。
一個連接上打開多個流,還可以雙向數據傳輸,輕松突破6路并行限制。
思考一下:在http1時代的把資源散列在不同域名下還有效嗎?實際上非但不能提升性能,反而會新增連接開銷。

突破6路限制就夠了嗎?我們再來看看另一個很容易被忽略的部分:http頭部損耗。
http請求中,每次請求都會包含一系列的請求頭來描述請求的資源和特性等。而頭部沒經過任何壓縮,每次請求都要占用200-800個字節,如果帶上一個比較大的cookie,甚至會超過1K;
而我們實際的日志數據大小僅僅只有10 - 50字節,頭部消耗占了90%以上;
另外,據Htpp Archive統計數據,平均每個頁面上百個請求,越來越多的流量消耗在頭部;
最致命的是,UserAgent等信息不會頻繁變動,每次請求都傳輸是一種嚴重的浪費。

再次利用h2頭部壓縮。先來看看采用h1和h2的效果對比。
h1下請求大小295 字節, 而h2僅僅只有18 字節,大小只有區區16分之一,請求時間也從6ms降低到了4毫秒。

太神奇了,來快速地過一下http2頭部壓縮是如何實現的:
首先協議里預設了一個靜態字典,用來表示常用的頭部字段,比如圖中,2就是 method get. 以前需要把完整的key-value對發過去,現在只需要把一個數字發過去,大小大幅縮小。
其次,客戶端和服務端會共同維護一個動態表,動態表用來干啥呢?舉個例子,比如useragent, 每個用戶的useragent值是不一樣的,沒法放到靜態表中去約定。但是對于同一個用戶會話,useragent是不會改變,這樣的值,就由客戶端和服務端協商決定存入動態表,這樣第一次傳輸過去之后,以后就只需要傳入動態表中的一個編碼就行了,圖中的62和63就是這樣的情況。連接中發送的請求越多,就越能豐富動態表中的值,越到后面,請求性能越好(佐證了域名散列的方式不可取)。
還有一類情況,值總是變來變去,也沒法保存到動態表中。這時候,只能直接壓縮了。在h2中采用的是Huffman壓縮算法,能把數字或字符最短壓縮到5個字節,最大壓縮率是37.5%。

其實除了頭部壓縮外,還有很多辦法減少體積,比如
采用http 204返回無響應體的response;
采用post請求合并多條日志,共用請求頭;
錯誤調用堆棧中經常會出現很多的文件url,占了不少空間,可以考慮將他們抽取成一個變量;
時間關系,日志采集部分就到此為止。

接下來我們來看看一個監控系統最核心的部分:實時計算。
實時計算采用的是業界已經非常成熟的流計算,簡單地過一下概念。
這是一張表示流計算的經典結構圖,有兩種組件,水龍頭是spout,代表數據源, 閃電是bolt, 代表處理邏輯。這里面有兩個很重要的特征。
其一是計算能力彈性,如果有更大的日志量流入,能夠動態調度更多的算力來保障計算的實時性;
其二是反壓。每個計算節點都可以根據自己的負載情況反壓上一級的計算節點,從而實現計算任務的更合理地分配。

思考一下:如何在海量日志中實時取到限定條件的聚合數據?如圖所示,我想實時拿到【模擬頁面】在【廣東省】【最近24小時】【訪問速度】走勢。
分析一下,如果需要畫出這樣的走勢圖,每個小時畫一個點,需要取24個點的值,每個節點寫個SQL把符合條件的數據求平均,如果數據量很小的時候,取24次數據勉強性能上勉強可以忍受。
但是如果作為一個SASS系統,監控系統會接入非常多的項目,每時每刻都有大量的數據上報。系統也會積累海量的數據。取一個節點需要多少時間呢?參考離線計算大概要15分鐘, 24個節點,預估需要6個小時。這明顯是不可接受的。那阿里云前端監控是如何做到實時拿數據的呢?

這就需要用到我們的大數據處理神器dataCube(數據立方),我們來剖析下數據立方是如何解決實時性的問題的。
如圖所示: 拿瀏覽器、設備、地理區域三個維度為例,組成一個三維的數據立方。立方中的每個小格子代表一個聚合數據。
請看圖中數字3所在的格子,3代表三維,也就是Vivo設備、chrome瀏覽器在北京地區的聚合量。
再看一個黃色切面上的數字2,黃色切面代表瀏覽器維度的聚合,也就是上海地區Vivo設備的聚合量,包括所有的瀏覽器。
再看最右下角的數字0代表0維,也就是所有的聚合量,包括所有的瀏覽器、所有的設備、所有的地區。
數據立方的秘密就是把所有格子的值都預先計算出來,下次要取值,直接取數據立方的某個值就好了,本質上是一種空間換時間的思路。

看一個我們實際的處理場景,元數據經過流計算之后,每個每分鐘、每小時、每天都會產生一個數據立方。而這個數據立方多達90多維?;氐街暗陌咐?,如果我想限定若干個條件拿到24小時趨勢圖,我只需要24個數據立方中把指定位置的小格子取出來就行了。計算時間就能大幅壓縮到秒級別。
原文鏈接

科技資訊:

科技學院:

科技百科:

科技書籍:

網站大全:

軟件大全:

熱門排行
女人个人私人电话联系杭州的|热久久久久香蕉无品码|爱情岛亚洲永久自拍品质|国产丶欧美丶日本不卡