摘要: 今天我分享的內容分紅三個部分: 第一部分是「大前端時代前端監控新的變化」, 講述這些年來,前端監控一些新的視角以及最前沿的一些思考。 第二部分"前端監控的最佳實踐", 從使用的角度出發,介紹前端監控系統的各類使用姿式 最後是「阿里雲ARMS前端監控系統架構」, 簡單地剖析下,阿里雲前端監控系統是怎麼實現的。前端
本文來自阿里雲前端監控團隊,轉載請註明出處
本文爲2018年6月21日,在北京舉辦的GMTC(全球大前端技術大會),下午性能與監控專場,由阿里雲前端監控團隊前端技術專家彭偉春帶來的演講稿,現場反饋效果很是好,地上都坐了三圈,不少人反饋根本沒法擠進去。先上現場照。git
正文從這裏開始~github
你們下午好,今天我給你們帶來的主題是《大前端時代前端監控的最佳實踐》。web
先作一個自我介紹,我叫彭偉春,英文名是Holden, 阿里花名是六猴, 你們都叫我猴哥。是阿里開源同構框架beidou的做者,目前是阿里雲前端系統技術負責人。ajax
今天我分享的內容分紅三個部分:算法
先進入咱們第一個環節 大前端時代前端監控新的變化。
要了解前端監控新的變化,還得先看看前端這些年發生了哪些變化:chrome
前端這些年發生了翻天覆地的變化,又會給監控帶來什麼呢?讓咱們思考下如下幾個問題:後端
接下來我和你們一塊兒探討其中的一兩項瀏覽器
早些年,SPA如此盛行,咱們也在業務中作了嘗試,體驗是大幅提高了,可業務方卻吐槽PV降低了。緩存
那究竟是什麼致使了PV降低了呢?在後端直出時代,咱們每一次的交互,都是向後端請求一個新的頁面,PV天然就高,改爲SPA模式以後,大量的頁面請求變成了頁內路由,或者說是頁內轉場。那如何解呢?這難不倒咱們,大部分框架路由都是基於哈希實現的,咱們只要偵聽hash改變,每次改變上報一次PV就行了。也有少許的路由並非基於哈希實現的,好比angular, 這時候就須要輕量級地hack pushState和replaceState。
這樣就完美了嗎?
咱們再思考下如下幾個案例
其實還有不少其它層出不窮的場景,具體該如何去統計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, 也就是主要內容可見時間,那什麼是主要內容? 每一個人得出的結論可能會不同。
先作一個猜測:主要內容 = 頁面渲染過中元素增量最大的點。
先經過飛豬案例作一次驗證。
猜測成立。
再經過手淘案例作一次驗證。
猜測不成立。
那究竟是什麼緣由致使咱們的猜測不成立?
根據上面的修正因子。咱們從新設計了一遍算法, 計算每次變化的得分,一塊兒來看看,算法是如何實現的?
如圖所示分爲三個步驟
若是每次都去遍歷新增元素並計算是否可見是很是消耗性能的。實際上採用的是深度優先算法,若是子元素可見,那父元素可見,再也不計算。 一樣的,若是最後一個元素可見,那前面的兄弟元素也可見。經過深度優先算法,性能有了大幅的提高。
再拿以前的手淘案例來驗證一遍。
通過改良以後,第三屏主要內容的得分是最高的,符合預期。
那麼接下來首屏統計又會發生什麼樣的變化呢?其實統計首屏時間自己就是瀏覽器的職責,交由瀏覽器來處理是最好的。目前W3C關於首屏統計已經進入了提議階段,坐等W3C再次標準化。你們能夠在github上看到最新進。
限於篇幅,前端監控其它新的變化再也不展開。講了這麼多前端監控的新變化,那什麼纔是打開前端監控最最正確地姿式呢?
由此進入咱們的第二個環節,「前端監控的最佳實踐」。
我用一個表達式「要是什麼什麼就行了」來總結。我常常會想【要是天上能掉錢就行了】,【要是有個機器人幫我寫代碼就行了】。一樣的,每次發版以後都是提醒吊膽的,不知道用戶到底能不能正常使用。(這時候你就會想)要是能有雙眼睛幫我盯着系統就行了;每次出錯,都是用戶投訴反饋問題,實際等到用戶主動反饋問題,影響面已經很是大了: (這時候你就會想)要是能在第一時間發現錯誤就行了;
還真有這樣的案例,前年雙十一凌晨值班,忽然收到郵件和短信告警,因而點開了詳情。
發如今接口成功率趨勢圖中,接口請求量大幅上升,伴隨着成功率急劇降低,再查看錯誤信息聚合模塊,發現頻率最高的錯誤信息是【交易規則衝突】,深度排查以後,最終找出了緣由,是運營配置的雙十一優惠規則和平時優惠規則產生了衝突,致使下單失敗。最後凌晨4點申請了緊急發佈修復了衝突,解除告警。
由此能夠得出最佳實踐之一:主動監控。固然主動監控的內容不只侷限於API成功率,也包括JS錯誤率等。稍微總結下流程:先是配置告警規則; 而後就能夠放心大膽地睡覺了,若有任何風吹草動,系統立刻會通知到咱們,再經過錯誤聚類模塊,精準地定位問題。再手起刀落,bug修復完成。
再回到咱們的【要是什麼什麼就行了】,在作性能優化的時候,有時候明明總體性能已經不錯了,可恰恰有少許用戶以爲很慢:(這時候你就會想)要是能知道慢速用戶發生了什麼就行了。
這時候咱們就須要用到【性能樣本分佈】,打開頁面性能頁面,查看0 -60秒之間每一個區間的性能樣本分佈狀況,從分佈圖中能夠看出來大部分用戶加載時間都在2秒之內,極少數部分用戶的頁面時間在10秒左右的。
拖動下面的滑塊,縮小時間範圍到10S左右,這時候系統就會篩選出10秒左右的慢會話。
點擊展開某次慢會話,不只能夠看到此次慢會話的基本信息,好比網絡類型等,還能夠看到完整的資源加載瀑布圖,能夠清晰地看出來,具體是什麼資源致使整個會話變慢。由此咱們又能夠得出最佳實踐之二:慢會話追蹤
再回到咱們的【要是什麼什麼就行了】,有時候用戶提交了一條反饋,某某功能出錯用不了,這時候你又不知道用戶端到底報了什麼錯,是否是又得打電話給用戶,還得手把手教用戶如何經過瀏覽器開發者工具把錯誤截圖下來發你。我哩個去,用戶這個時候極可能由於系統太爛了,已經不堪其辱,早就把頁面關了而且發誓不再用這破系統。(這時候你就會想)要是能知道用戶報了什麼錯就行了。
別怕,打開阿里雲前端監控的【訪問明細】搜索用戶ID,直接能夠看到該用戶在訪問過程當中,到底報了什麼錯。
有時候拿到了用戶報錯時的基本信息,也知道用戶報了什麼錯,可是在本身電腦上調試的時候,不管如何也復現不了,這個時候是否是又得去和用戶溝通,讓用戶描述重現路徑,實際上用戶可能本身都忘了具體怎麼作才能重現錯誤。(這時候咱們就會想)要是能重現用戶行爲就行了。
【視頻演示】咱們現場來模擬一次用戶出錯還原,左邊是用戶實際操做的屏幕,爲了更好地展現效果,我把用戶行爲實時地展現在右邊的屏幕上:
第一步: 模擬用戶在淘寶頁面上作出了一系列的操做, 鼠標移動、滾動頁面,搜索等;
第二步:假設忽然出現了某某錯誤,這時系統會把記錄的用戶行爲存儲到服務端;
第三步: 開發人員經過會話ID查詢到出錯行爲,最終進行還原。你們能夠看到左邊屏幕再也不操做,右邊屏幕還原出了以前出錯的全部行爲。
你們必定在想這麼炫酷的能力是如何實現的呢?接下來就爲你們揭祕阿里雲前端監控系統背後的技術架構。
就從你們最感興趣的錯誤還原講起,你們可能在猜想,是否是把整個頁面錄製成視頻了。其實不是這樣的,視頻太大了,不可能出錯了把一個視頻發到服務端,這樣是對用戶資源的嚴重浪費。先看示意圖(跟着箭頭從左到右):
你們可能以爲還不過癮,接下來爲你們講一下阿里雲ARMS前端監控系統的總體架構。
首先從左到右分紅三個域。分別是日誌採集域,日誌分析域和監控告警域。在日誌採集域,客戶端經過SDK將信息上報到Nginx服務器, 日誌服務SLS在Nginx服務器上起一個agent,去把日誌信息同步過去,日誌到了SLS就至關於到了一個大的蓄水池。再經過實時計算引擎的計算,結果部分存儲到HBase,另外一部分結果回存到SLS日誌服務用於搜索。
最終經過restful API向前端提供數據,前端渲染出數據dashboard.
是否是感受很簡單地樣子,有句話叫作【看山跑死馬】,山看起來就在眼前, 可就算騎馬過去馬都會累死。那就讓咱們一塊兒來揭開它的神祕面紗吧。
接下來重點介紹跟前端同窗工做密切相關的日誌採集域,相比業界,咱們的日誌採集仍是有不少可圈可點之處的。好比說:
這些內容我都不詳細展開,那接下來我重點講一下,阿里雲前端監控是如何突破侷限優雅地上報日誌
你們都知道,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個數據立方中把指定位置的小格子取出來就好了。計算時間就能大幅壓縮到秒級別。