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

摘要:
今天我分享的內容分紅三個部分: 第一部分是「大前端時代前端監控新的變化」, 講述這些年來,前端監控一些新的視角以及最前沿的一些思考。 第二部分"前端監控的最佳實踐", 從使用的角度出發,介紹前端監控系統的各類使用姿式 最後是「阿里雲ARMS前端監控系統架構」, 簡單地剖析下,阿里雲前端監控系統是怎麼實現的。

本文來自阿里雲前端監控團隊,轉載請註明出處html

本文爲2018年6月21日,在北京舉辦的GMTC(全球大前端技術大會),下午性能與監控專場,由阿里雲前端監控團隊前端技術專家彭偉春帶來的演講稿,現場反饋效果很是好,地上都坐了三圈,不少人反饋根本沒法擠進去。先上現場照。前端

gmtc現場 | left

正文從這裏開始~git

IMAGE | left

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

IMAGE | left

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

IMAGE | left

今天我分享的內容分紅三個部分:ajax

  • 第一部分是「大前端時代前端監控新的變化」, 講述這些年來,前端監控一些新的視角以及最前沿的一些思考。
  • 第二部分"前端監控的最佳實踐", 從使用的角度出發,介紹前端監控系統的各類使用姿式。
  • 最後是「阿里雲ARMS前端監控系統架構」, 簡單地剖析下,阿里雲前端監控系統是怎麼實現的。

IMAGE | left

IMAGE | left

先進入咱們第一個環節 大前端時代前端監控新的變化。
要了解前端監控新的變化,還得先看看前端這些年發生了哪些變化:算法

  • 首先是Gmail的橫空出世,開啓了SPA的時代
  • Backbone/Angular等框架帶來了MVVM模式的同時,也把JS從腳本語言提高到了工程語言
  • React Native/Weex把移動端開發從Hybrid模式進化到了跨端開發模式
  • Node.js問世爲前端帶來了更多的可能性

IMAGE | left

前端這些年發生了翻天覆地的變化,又會給監控帶來什麼呢?讓咱們思考下如下幾個問題:chrome

  • 傳統監控模式可否適用於新的技術?好比PV統計
  • SPA模式下首屏如何計算?
  • 跨端開發給監控帶來什麼什麼挑戰?
  • 前端監控的上報模式在Node.js端是否合理?
  • 接下來我和你們一塊兒探討其中的一兩項

IMAGE | left

早些年,SPA如此盛行,咱們也在業務中作了嘗試,體驗是大幅提高了,可業務方卻吐槽PV降低了。後端

IMAGE | left

那究竟是什麼致使了PV降低了呢?在後端直出時代,咱們每一次的交互,都是向後端請求一個新的頁面,PV天然就高,改爲SPA模式以後,大量的頁面請求變成了頁內路由,或者說是頁內轉場。那如何解呢?這難不倒咱們,大部分框架路由都是基於哈希實現的,咱們只要偵聽hash改變,每次改變上報一次PV就行了。也有少許的路由並非基於哈希實現的,好比angular, 這時候就須要輕量級地hack pushState和replaceState。瀏覽器

IMAGE | left

這樣就完美了嗎?

IMAGE | left

咱們再思考下如下幾個案例

  • 某新聞類的網站,每次看完以後,都會下拉刷新,加載新的內容,這個時候是算一次PV仍是屢次?
  • 天貓商品列表頁,看完一屏以後,向上滾動會再加載新的一屏,PV該算一次仍是屢次?
  • 阿里雲郵後臺一直開着,每週上百次查看,是算一個PV仍是每次查看都計算一次?
  • 未關閉的瀏覽器tab幾小時以後再次瀏覽,該不應再計一次PV?
  • 查找信息時,瀏覽器Tab之間快速切換,切換過程當中要不要計一次PV?

    其實還有不少其它層出不窮的場景,具體該如何去統計PV留給你們去思考, 再也不展開。
    複製代碼

IMAGE | left

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

IMAGE | left

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

IMAGE | left

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

IMAGE | left

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

IMAGE | left

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

IMAGE | left

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

IMAGE | left

先經過飛豬案例作一次驗證。

IMAGE | left

猜測成立。

IMAGE | left

再經過手淘案例作一次驗證。

IMAGE | left

猜測不成立。

IMAGE | left

那究竟是什麼緣由致使咱們的猜測不成立?

  • 首先是元素是否可見, 不可見的元素對用戶的影響基本爲0。
  • 其次是每一個元素對頁面的影響是否等效?由此引出權重,不一樣的元素採用不一樣的權重計算影響。阿里雲前端監控

IMAGE | left

根據上面的修正因子。咱們從新設計了一遍算法, 計算每次變化的得分,一塊兒來看看,算法是如何實現的?
如圖所示分爲三個步驟複製代碼
  1. 偵聽頁面元素的變化;
  2. 遍歷每次新增的元素,並計算這些元素的得分總;
  3. 若是元素可見,得分爲 1 * weight(權重), 若是元素不可見,得分爲0;

若是每次都去遍歷新增元素並計算是否可見是很是消耗性能的。實際上採用的是深度優先算法,若是子元素可見,那父元素可見,再也不計算。 一樣的,若是最後一個元素可見,那前面的兄弟元素也可見。經過深度優先算法,性能有了大幅的提高。

IMAGE | left

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

image | left

通過改良以後,第三屏主要內容的得分是最高的,符合預期。

IMAGE | left

那麼接下來首屏統計又會發生什麼樣的變化呢?其實統計首屏時間自己就是瀏覽器的職責,交由瀏覽器來處理是最好的。目前W3C關於首屏統計已經進入了提議階段,坐等W3C再次標準化。你們能夠在github上看到最新進。

限於篇幅,前端監控其它新的變化再也不展開。講了這麼多前端監控的新變化,那什麼纔是打開前端監控最最正確地姿式呢?

IMAGE | left

由此進入咱們的第二個環節,「前端監控的最佳實踐」。

IMAGE | left

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

IMAGE | left

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

IMAGE | left

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

IMAGE | left

由此能夠得出最佳實踐之一:主動監控。固然主動監控的內容不只侷限於API成功率,也包括JS錯誤率等。稍微總結下流程:先是配置告警規則; 而後就能夠放心大膽地睡覺了,若有任何風吹草動,系統立刻會通知到咱們,再經過錯誤聚類模塊,精準地定位問題。再手起刀落,bug修復完成。

IMAGE | left

再回到咱們的【要是什麼什麼就行了】,在作性能優化的時候,有時候明明總體性能已經不錯了,可恰恰有少許用戶以爲很慢:(這時候你就會想)要是能知道慢速用戶發生了什麼就行了。

IMAGE | left

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

IMAGE | left

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

IMAGE | left

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

IMAGE | left

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

IMAGE | left

有時候拿到了用戶報錯時的基本信息,也知道用戶報了什麼錯,可是在本身電腦上調試的時候,不管如何也復現不了,這個時候是否是又得去和用戶溝通,讓用戶描述重現路徑,實際上用戶可能本身都忘了具體怎麼作才能重現錯誤。(這時候咱們就會想)要是能重現用戶行爲就行了。

IMAGE | left

【視頻演示】咱們現場來模擬一次用戶出錯還原,左邊是用戶實際操做的屏幕,爲了更好地展現效果,我把用戶行爲實時地展現在右邊的屏幕上:

  • 第一步: 模擬用戶在淘寶頁面上作出了一系列的操做, 鼠標移動、滾動頁面,搜索等;
  • 第二步:假設忽然出現了某某錯誤,這時系統會把記錄的用戶行爲存儲到服務端;
  • 第三步: 開發人員經過會話ID查詢到出錯行爲,最終進行還原。你們能夠看到左邊屏幕再也不操做,右邊屏幕還原出了以前出錯的全部行爲。

IMAGE | left

你們必定在想這麼炫酷的能力是如何實現的呢?接下來就爲你們揭祕阿里雲前端監控系統背後的技術架構。

IMAGE | left

就從你們最感興趣的錯誤還原講起,你們可能在猜想,是否是把整個頁面錄製成視頻了。其實不是這樣的,視頻太大了,不可能出錯了把一個視頻發到服務端,這樣是對用戶資源的嚴重浪費。先看示意圖(跟着箭頭從左到右):

  • 首先,每一次會話都有一個惟一的session ID,這是串聯起全部行爲的紐帶。
  • 其次,用戶行爲又分紅兩個部分,其一是用戶的操做,好比鼠標滑動,點擊,頁面滾動等,其二是頁面的變化。這二者咱們都統稱爲用戶行爲,記錄在同一個隊列中。
  • 一開始的時候,系統會記錄下初始的頁面做爲第一幀,這是惟一的一次完整頁面記錄。
  • 針對用戶操做,咱們會記錄事件的類型,鼠標位置等關鍵信息,保存到隊列中。
  • 針對頁面變更,咱們會起一個mutationObserve偵聽頁面的改動,每次只記錄改動的部分,保存到隊列中。
  • 不管是事件仍是頁面改動,都是對等的一幀,每一幀都會有當前時間,與上一幀間隔時間等基本信息用戶還原。
  • 一旦出錯,SDK就把隊列發送到監控系統,並清空當前隊列。
  • 還原端根據記錄的行爲隊列,根據時間逐一播放出來。最終造成一個相似於視頻的效果。

IMAGE | left

你們可能以爲還不過癮,接下來爲你們講一下阿里雲ARMS前端監控系統的總體架構。
首先從左到右分紅三個域。分別是日誌採集域,日誌分析域和監控告警域。在日誌採集域,客戶端經過SDK將信息上報到Nginx服務器, 日誌服務SLS在Nginx服務器上起一個agent,去把日誌信息同步過去,日誌到了SLS就至關於到了一個大的蓄水池。再經過實時計算引擎的計算,結果部分存儲到HBase,另外一部分結果回存到SLS日誌服務用於搜索。
最終經過restful API向前端提供數據,前端渲染出數據dashboard.
是否是感受很簡單地樣子,有句話叫作【看山跑死馬】,山看起來就在眼前, 可就算騎馬過去馬都會累死。那就讓咱們一塊兒來揭開它的神祕面紗吧。

IMAGE | left

接下來重點介紹跟前端同窗工做密切相關的日誌採集域,相比業界,咱們的日誌採集仍是有不少可圈可點之處的。好比說:

  • 靜默採集: 只須要一行代碼接入SDK就好了,全部的API請求、資源加載、JS錯誤、性能等都自動監控起來了。省去了繁瑣的配置。
  • 單元測試 + 自動化測試:前端監控的目的就是去監控前端的異常狀況,不給頁面帶來新的異常這是咱們的底線,對此,咱們有完善的單元測試和自動化測試去保障SDK自己的質量。
  • (SDK出錯隔離):但實際上任何系統都不能保證本身不會出錯,那麼萬一SDK自己報錯了,咱們還有異常隔離機制,確保出錯也不會影響業務的運行。

IMAGE | left

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

IMAGE | left

那如何突破限制呢?有一個絕招:就是升級到http2, 利用h2的多路複用特性。
一個鏈接上打開多個流,還能夠雙向數據傳輸,輕鬆突破6路並行限制。

  • 思考一下:在http1時代的把資源散列在不一樣域名下還有效嗎?實際上非但不能提高性能,反而會新增鏈接開銷。

IMAGE | left

突破6路限制就夠了嗎?咱們再來看看另外一個很容易被忽略的部分:http頭部損耗。

  • http請求中,每次請求都會包含一系列的請求頭來描述請求的資源和特性等。而頭部沒通過任何壓縮,每次請求都要佔用200-800個字節,若是帶上一個比較大的cookie,甚至會超過1K;
  • 而咱們實際的日誌數據大小僅僅只有10 - 50字節,頭部消耗佔了90%以上;
  • 另外,據Htpp Archive統計數據,平均每一個頁面上百個請求,愈來愈多的流量消耗在頭部;
  • 最致命的是,UserAgent等信息不會頻繁變更,每次請求都傳輸是一種嚴重的浪費。

IMAGE | left

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

IMAGE | left

太神奇了,來快速地過一下http2頭部壓縮是如何實現的:

  • 首先協議裏預設了一個靜態字典,用來表示經常使用的頭部字段,好比圖中,2就是 method get. 之前須要把完整的key-value對發過去,如今只須要把一個數字發過去,大小大幅縮小。
  • 其次,客戶端和服務端會共同維護一個動態表,動態表用來幹啥呢?舉個例子,好比useragent, 每一個用戶的useragent值是不同的,無法放到靜態表中去約定。可是對於同一個用戶會話,useragent是不會改變,這樣的值,就由客戶端和服務端協商決定存入動態表,這樣第一次傳輸過去以後,之後就只須要傳入動態表中的一個編碼就好了,圖中的62和63就是這樣的狀況。鏈接中發送的請求越多,就越能豐富動態表中的值,越到後面,請求性能越好(佐證了域名散列的方式不可取)。
  • 還有一類狀況,值老是變來變去,也無法保存到動態表中。這時候,只能直接壓縮了。在h2中採用的是Huffman壓縮算法,能把數字或字符最短壓縮到5個字節,最大壓縮率是37.5%。

IMAGE | left

其實除了頭部壓縮外,還有不少辦法減小體積,好比

  • 採用http 204返回無響應體的response;
  • 採用post請求合併多條日誌,共用請求頭;
  • 錯誤調用堆棧中常常會出現不少的文件url,佔了很多空間,能夠考慮將他們抽取成一個變量;

    時間關係,日誌採集部分就到此爲止。
    複製代碼

IMAGE | left

接下來咱們來看看一個監控系統最核心的部分:實時計算。
實時計算採用的是業界已經很是成熟的流計算,簡單地過一下概念。
這是一張表示流計算的經典結構圖,有兩種組件,水龍頭是spout,表明數據源, 閃電是bolt, 表明處理邏輯。這裏面有兩個很重要的特徵。

  • 其一是計算能力彈性,若是有更大的日誌量流入,可以動態調度更多的算力來保障計算的實時性;
  • 其二是反壓。每一個計算節點均可以根據本身的負載狀況反壓上一級的計算節點,從而實現計算任務的更合理地分配。

IMAGE | left

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

IMAGE | left

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

IMAGE | left

看一個咱們實際的處理場景,元數據通過流計算以後,每一個每分鐘、每小時、天天都會產生一個數據立方。而這個數據立方多達90多維。回到以前的案例,若是我想限定若干個條件拿到24小時趨勢圖,我只須要24個數據立方中把指定位置的小格子取出來就好了。計算時間就能大幅壓縮到秒級別。

相關文章
相關標籤/搜索