GMTC 大前端時代前端監控的最佳實踐

摘要: 今天我分享的內容分成三個部分: 第一部分是“大前端時代前端監控新的變化”, 講述這些年來,前端監控一些新的視角以及最前沿的一些思考。 第二部分"前端監控的最佳實踐", 從使用的角度出發,介紹前端監控系統的各種使用姿勢 最後是“阿里雲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個數據立方中把指定位置的小格子取出來就行了。計算時間就能大幅壓縮到秒級別。

原文鏈接


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章