70%以上業務由H5開發,手機QQ Hybrid 的架構如何優化演進?
隨著前端開發的興起,QQ也逐漸演變為Web與原生終端混合的開發模式。得到Web動態運營能力的同時,QQ也在交互響應速度、后臺服務壓力、海量用戶集的帶寬沖擊等方面,受到了更多的挑戰。在快速的Web運營節奏下,必須保證嵌入QQ的第三方業務也始終處于一個高質量的服務狀態。針對這些問題,QQ團隊除了采用動態CDN、后臺渲染等全棧手段優化體驗,也構建了圍繞速度、成功率、頁面異常等維度的監控體系來保障服務質量。
寫在前面
首先自我介紹,我叫涂強。我于2005年加入騰訊,那個時候還不流行移動端、hybrid等開發。我當時主要開發PC版本的QQ,后來負責PC版QQ UI引擎的時候做過一些嘗試,即在PC客戶端上集成瀏覽器內核,那個時候做了一些H5和native混合開發的框架性工作。之后我加入了騰訊QQ會員團隊,負責QQ會員在移動終端上的技術,同時也有很艱巨的任務:維護手機QQ中的所有H5 hybrid開發的框架,即WebView組件的技術工作。
言歸正傳,現在主流的hybrid還是H5 + native,H5開發對現在移動終端的重要性不必多提,但H5在native中很明顯的問題大家都看得到,比如打開應用的時候要等很久的頁面loading,loading時用戶看到轉菊花的界面很可能就流失掉,這也是產品經理不想看到的狀況。還有一點是每次打開H5都涉及到網絡交互、文件下載,這些操作會消耗用戶的流量,如果流量消耗大用戶也會不高興。
今天給大家分享的內容主要是介紹QQ會員團隊如何在頁面打開時間以及用戶流量方面所做的優化,分別對應sonic和reshape的兩個自主技術框架。
傳統頁面的動靜分離
所有的技術選型與框架都是要結合業務形態來選擇,大家對QQ會員的業務形態可能有簡單的了解。手機QQ中可以說有大概70%以上的業務由H5開發,像會員的主要商城:游戲分發中心、會員特權中心和我現在負責的個性化業務的商城等等。這些商城特點很明顯,它們不是UGC生成的頁面,是產品經理在后臺配置的內容,比如在頁面上可以看到的表情和主題等等。
這些頁面相對傳統,在最初的時候,一個傳統的H5頁面為了提升速度和體驗會做一些動靜分離的優化,比如頁面頂部的banner以及下面我們稱作為item的物品區域,這些區域的數據可以由產品經理自由編輯隨時更換,我們會通過頁面loading之后發起CGI請求,從dataServer獲取數據,然后再拼接起來。
這里的流程大概如下,用戶從click開始,到launch WebView,WebView去加載CDN上的HTML文件,頁面loading起來后才會去獲取JSON,為了加速這個過程可能會用到localStroage做緩存,這整個過程是非常傳統的靜態頁面加載過程,相對比較簡單。
但上述方案有一些問題,比如我們在launch WebView的時候網絡處于空等狀態,這會浪費時間。我們團隊內部統計了Android機器launch WebView大概需要1秒以內(因為手機QQ是多進程的架構,WebView生存在另一個進程內部,launch一次WebView除了進程loading還有瀏覽器內核的加載)。
其次,發布在CDN上的靜態頁面內部不包含item數據,所以用戶第一眼看到從CDN下載的頁面,里面的banner區域和item區域處于一片空白,這對用戶體驗也是很大的傷害。
還有一個問題,頁面loading起來要refresh當前的DOM,即拉取JSON之后拼接DOM結構再refresh,我們發現在一些QQ用戶所使用的低端Android機器里,這個執行也會非常消耗時間。
靜態直出+離線預推
面對這些問題我們大膽采取了一些技術手段,我們稱之為靜態直出+離線預推的模式。首先我們把WebView的加載和網絡請求做了并行,我們所有的網絡請求并不是從WebView內核發起request,而是loading WebView的過程中,我們通過native的渠道建立自己的HTTP鏈接,然后從CDN和我們稱作offlineServer的地方獲取頁面,這個offlineServer也就是大家聽說過的離線包緩存策略。
我們在native會有offlineCache,發起HTTP請求的時候首先檢查offlineCache里有沒有當前HTML緩存,這個緩存和WebView的緩存是隔離的,不會受到WebView的緩存策略影響,完全由我們自控。
如果offlineCache沒有緩存才會去offlineServer去同步文件,同時也會去從CDN去下載更新。我們在CDN上存儲的HTML已經把banner和item等所有的數據打在靜態頁面里,這個時候WebView只要拿到HTML就不需要再做refresh和執行任何JS,整個頁面可以直接展示出來,用戶也可以進行交互。
這個方案首先會節省WebView launch的時間,這段時間可以直接網絡傳輸,另外如果本地有offlineCache甚至也不需要網絡傳輸請求,相當于完全加載一個本地頁面。但很多時候我們為了保險起見,還是加了頁面loading,然后做refresh的操作防止數據的不一致性。
這套機制上線后效果不錯,但真的去實施這種H5加載模式會遇到一些坑,例如產品經理配置的banner圖片和item數據可能會存在多份數據版本不一致的情況。
產品經理肯定是在dataServer上配置最新數據信息,但CDN上的頁面內置的數據有可能仍處于上一版本,更差的情況是離線包服務器和offlineServer生成的HTML又是另外一個版本。當用戶本地的緩存和server同步不及時即常見的緩存刷新問題,很有可能存儲的數據又是另外一份。
所以這套系統剛開始灰度試用的時候,產品經理很快就找我們吐槽:打開頁面時看到的是一份數據,過了一秒頁面刷新后看到的內容又不一樣,而且每次進入頁面都會發生這種情況。
如何統一數據
如何快速把四個版本的數據全部統一?我們針對靜態直出這種模式做了小型的自動構建系統,產品經理在管理端配置數據要同步dataServer時,我們會立刻啟動我們內部稱為vnues的構建系統。
這套系統是基于Node.js搭建的,會把開發所編寫的代碼文件和UI素材圖片等等數據實時生成最新版本的HTML,然后發布到CDN以及同步到offlineServer上,這可以解決CDN的文件與最新數據不一致的問題。
但離線包緩存是放在用戶手機上的,我們如何最快速地把用戶手機上的離線緩存也更新起來?大家可能會這么做:QQ客戶端每次登錄上來把offlineServer最新文件下載回來就好了,但這個方案會遇到巨大的流量挑戰。
QQ現在每天的活躍用戶好幾億,登錄峰值差不多十幾萬每秒,即使一個100KB離線包的更新,發布一次動輒就需要幾百GB的帶寬,無論從成本還是技術層面都不是我們能接受的事情。
我們offlineServer內部分為流控和offline計算兩部分。當一個頁面的所有資源需要進行離線包計算打包的時候,offline計算這部分除了把所有的資源打包,內部也會存儲之前所有的歷史版本,同時根據歷史版本和最新版本生成所有的diff,即每個離線包的差樣部分。
這個方案也是根據我們業務形態而定的,因為每次產品經理更新的頁面數據并不會太多,基本是幾KB到10+KB的范圍,所以我們沒有必要每次離線包的更新都讓用戶去下載全量的包。
當QQ用戶登錄后,每次都會詢問offline流控server看有沒有最新的包可以下載,如果當前流控server統計的帶寬在可接受的成本(目前暫定為10GB到20GB的空間),當CDN的帶寬撐得住的時候就會把最新的diff下發給客戶端,這樣就做到離線包一有更新時客戶端能以最小的流量代價得到刷新。
數據以及效果
通過這套系統,我們只花了十幾GB的帶寬,就把整個BG所有H5業務的離線包覆蓋率維持在大概80%到90%。從這個工作中我們也發現一個非常反常規的事情,即大家以為離線包預推會非常消耗帶寬,但其實只是偶爾預推才消耗大量帶寬;如果長年累月不停地推送,實際上對帶寬的消耗非常小,因為時時刻刻都保持在差量下發的狀態。
做了這個工作后我們采集了現網數據,靜態直出和傳統頁面這兩種模式對比非常明顯。下圖頁面耗時部分,由于靜態直出頁面不需要任何JS執行,只需要WebView渲染,所以頁面耗時靜態直出相比傳統頁面降低了大概500毫秒到1秒左右。
這里有趣的現象是離線包的性價比問題,可以看到傳統頁面使用離線包可以在網絡耗時部分節省700多毫秒,但靜態直出這種模式使用離線包只能節省300毫秒左右,這是因為使用靜態直出在網絡過程中所依賴的外部CSS和JS都已經直出到HTML內部了,不需要額外的網絡請求,所以其本身網絡耗時有所減少,這時使用離線包的收益開始逐漸下降。
這里可能有疑問,為什么靜態直出在離線包的情況下網絡耗時還需要800多毫秒,本地有緩存不應該是零耗時嗎?
我們統計的網絡耗時是從WebView load URL開始到頁面首行這段時間,實際上包括一部分頁面加載,WebView內核的啟動,網絡組件和渲染組件的加載,所以耗時比較高。
這里肯定也有優化空間,但當我們的客戶端團隊正要優化網絡耗時這部分的時候,我們的業務形態變了。之前是產品經理配置什么頁面就顯示什么,所有用戶看到的內容都是一樣的,現在產品經理說每個用戶進入到商城首頁看到的內容要完全不一樣。
以下圖為例,像左邊首頁的內容是隨機推薦的,右邊實際上是通過機器學習根據用戶過去表情發送的行為習慣和我們后臺的物品做計算匹配,根據用戶的喜好行為而推薦的內容。
每個用戶進來看到的內容都是不一樣,那么靜態直出這種模式行不通了,因為我們不可能把所有用戶的頁面都在后臺生成然后發到CDN上,然而這種模式也有很簡單的辦法來解決。
動態直出
我們并不在CDN上存儲HTML,而是后臺Node.js服務器上動態拼接出整個HTML文件,數據來源是從dataServer去拉取。
這種模式解決了產品的需求,但引入了新的問題。WebView獲取html要請求Node.js,Node.js要進行后臺頁面拼裝,中間的網絡耗時和后臺運算耗時比我們想象中要大。在這個過程中,整個頁面是無法渲染的,用戶進入我們商城首頁則看到一片空白,產品經理同樣無法接受,用戶也不買單。
另外這種模式下幾乎無法利用WebView本身的緩存,因為后臺直出同樣在CSS/JS已經全部都在后端執行,WebView很難將一個純粹的靜態HTML全部緩存下來。為了解決上述問題,我們引入了動態緩存的機制。
動態緩存
同樣我們不讓WebView直接訪問我們的Node.js服務器,我們在這中間加上之前提到地類似offlineCache的中間層sonicBridge,這個中間層首先會從Node.js服務器下載完整的HTML給WebView,同時會把下載回來的內容在本地完整地做緩存。
我們之前是全網所有用戶緩存同一份HTML,現在修正為全網用戶緩存的內容都是從真實server里拉回來的頁面。
當用戶第二次進入頁面時,sonicBridge會優先把本地緩存的頁面提交給WebView,用戶進入頁面不需要等待網絡請求就可以看到內容,這對用戶側在速度上的體驗提升比較大,但它又引入了另外一個問題。
實際上用戶每次打開WebView看到的內容都不一樣,Node.js每次返回的數據都是最新的,因此拉回來的數據我們必須讓WebView進行reload,這給用戶的體驗是:明明已經打開了本地緩存好的HTML并且看到內容,但一操作頁面卻整個reload了。在一些低端機型上WebView reload非常耗時,用戶能很明顯感覺到整個WebView H5頁面白屏一下,然后才刷新出新的內容。
結合前面提到的靜態直出局部refresh部分DOM的經驗,我們可以減少網絡傳輸量和減少提交頁面的數據量。我們首先做的事情是減少網絡傳輸量,避免refresh的時間太靠后。
減少傳輸數據
我們改變了Node.js組HTML的協議,當sonicBridge在第二次請求數據的時候,Node.js服務器并不會返回整個HTML給sonicBridge,而是返回給我們稱為data數據的部分。
拿到data數據之后,我們和H5頁面做了約定,由native側調用頁面的固定刷新函數,并傳遞數據給頁面。頁面會去局部刷新自己的DOM節點,這樣即使頁面需要刷新也不會reload整個頁面。
具體從數據內容的流程上看,首次sonicBridge加載頁面返回的仍是完整的HTML,同時會返回我們稱為template-tag的id,這個template-tag會標記這個頁面中靜態不變的那部分hash值,這措施是為了控制緩存。在返回的HTML中我們會也有一些標記,比如sonicdiff-banner,這個banner決定了它的刷新id是什么。
當第二次加載返回的數據就沒有前面看到的整個HTML,只會返回大概37KB的數據,這個data實際上就是一個JSON,但它定義了前面對應例如sonicdiff-banner的DOM結構。為了節省H5中執行的代碼,我們直接在JSON中把DOM節點代碼拼好,這樣頁面只需要做id的匹配和刷新。
這里37KB的傳輸數據很難避免,我們觀察到不同業務的刷新數據量還不一樣。能否能再減少一些提交給頁面去刷新的數據量呢,畢竟產品經理每次修改的數據也不會很多。
減少提交頁面數據
我們在sonicCache這一層除了前面提到的我們會緩存完整的HTML、template,還會把數據提取出來做dataCache。
template是在首次訪問的時候,根據sonicdiff里的id信息,把所有可變的數據剔除掉剩下的頁面框架。用戶二次打開時只要根據返回的數據,在客戶端本地和template做merge拼接就可以得到完整的HTML。
我們把每次的dataCache緩存下來后,對數據也做了差量,比如這一次請求返回的是37KB的數據,上次cache的也是37KB的數據,我們會判斷內部真正變化的到底有多少,然后只把差量的部分交給HTML刷新,這樣在大部分場景下我們的頁面只需要處理大概9KB的數據就能刷新整個頁面。
有了cache后用戶在本地打開的速度非常快,差量數據的傳輸也使得用戶刷新等待的時間減少了,最后加上這種數據提交時的diff使頁面刷新范圍也得到大幅的減少。
整個sonic模式流程如下,看上去比較復雜,但基本原理就是通過Bridge橋接把請求回的HTML分模版和數據進行緩存。
這里可能有疑問,前面靜態直出花力氣做的offlineServer和離線預推策略,在這里還有沒有用?事實上動態頁面和之前提到的靜態頁面離線緩存機制我們仍在使用,因為我們業務頁面還有大量公用JS,比如QQ提供的JS API封裝,還有一些共用的CSS也是通過離線包策略做的預推,這也是大家每次登錄的時候都會進行的下載。
數據以及效果
完成這種模式之后數據效果相對明顯,首次加載和普通的HTTP加載性能是差不多的,但用戶第二次打開頁面時,通常只需要1秒的時間就能看到頁面,這1秒鐘還包括客戶端launch進程和WebView的開銷,同時我們加載速度不再受用戶網絡環境的影響,不管是2G還是4G加載速度都接近一樣。
而且還帶來一個好處,如果用戶的網絡比較差,比如經常抖動連接不上,因為我們本地有緩存,因此就算用戶當前處于斷網狀態我們的頁面也能打開。
這里沒有提到模板更新的場景,模板更新是指我們抽取出來的template在我們server是有可能動態變化的,這個時候的加載流程和我們前面提到的就不太一樣了,當template有變化時,還是按照原來走HTML reload頁面的流程,這里的耗時相對偏高,但我們統計發現大部分用戶還是落在數據刷新也就是二次打開的狀態。
是否使用持久連接
在做H5的提速優化時,大家很容易想到我們是否要利用持久連接去避免訪問服務器的connect、DNS、握手之類的耗時,像QQ這種客戶端它跟后臺server是有持久化的連接的。假如用這個連接來向后臺服務器請求HTML文件并交給WebView,會不會比臨時建立一個connect請求更快呢?我們只需要搭一個反向代理服務就可以從QQ消息后臺訪問我們Node.js服務器,這個流程是可以打通,但是我們評估認為這種模式未必適合所有的場景。
確實是有一些App利用持久連接這種通道去加載頁面,但在手機QQ比較難行得通,因為手機QQ客戶端與sever的持久連接通道是一個非常傳統的CS架構,它發送的是socket package,每次需要發送一個請求包,收到應答之后才會繼續下一個請求。
這種應答機制決定了它每次都需要一個等待的過程,而且socket package的約束造成了每次傳輸的數據包的大小受到限制,像我們30+KB的數據很有可能要拆成五六個數據包,雖然是利用了持久連接節省了connect耗時,但和server多次來回通訊反而把整個耗時加大了。
另外,從Node.js服務器返回的數據是HTTP流式的,WebView不需要等待整個HTML加載完成后才能進行渲染和顯示,只要拿到傳輸中的first byte就可以開始進行document的解析以及DOM的構造。
如果要使用持久連接,我們很有可能要經過客戶端的加密解密以及組包等步驟,并且要等到整個HTML下載完成之后才能進行顯示,我們認為這個時間反而拖慢了性能。
QQHybrid架構
經過上述的介紹后,大家對QQHybrid可能有了大概直觀的印象:1. 我們在WebScope的前端開發同學做了一部分工作;2. 我們的native層終端開發同學做了bridge橋接,3.我們后臺的同學做了很多的自動集成和offlineServer推送等工作。該部分架構如下:
接下來我將介紹架構圖右邊關于頁面流量的部分。我們統計過各業務中關于流量的分布,如下圖,我們可以明顯看到大部分的流量都消耗在圖片資源上,但我們做這個分析時也曾經有懷疑,是不是業務特性決定了我們圖片消耗是最多的?手機QQ其他H5業務是不是也這樣?
春節紅包的流量分析
恰好我們有了一次機會,在2016年春節時手機QQ做了一次幾乎所有業務都有參與的活動——春節紅包,大家可能還有印象在2016年春節晚上時不停戳屏幕領紅包的操作。這種全民狂歡的背后帶來了巨大的流量壓力,每秒鐘大概給用戶發出30萬左右的禮包,引導用戶的web流量大概每秒鐘會有十幾萬次H5頁面的打開,當時評估的流量峰值超過1TB。
我們分析了里面的圖片流量,確實占據了接近一半的水平,有一部分我們已經走離線包預推的方式提前下發到用戶的手機中,但在活動期間現網的圖片流量仍超過了200GB。
流量并不是簡單花錢向運營商買就能解決的問題,春節的活動我們幾乎遇到了單域名下流量接近200GB的情況,當時CDN的架構已經快扛不住了。
我們都認為這里大有可為,如果圖片流量能節省的話,帶寬成本能夠降低。用戶側所消耗的網絡流量和手機電量等等體驗都能更好,所以我們團隊check了有關圖片格式方面的新東西。
SharpP的應用
大家都比較熟悉WebP,而且Android對其支持也比較好,而QQ團隊內部自己研發了叫SharpP的圖片格式,在文件大小上能比WebP節省10%左右的體積。下面是抽取我們CDN服務器上已有圖片進行的數據比對。
圖片體積是占優的,但解碼速度方面呢?我們分別使用了高、中、低端的機型分析,很不幸SharpP確實會比WebP甚至比JPG要慢一點,但幸運的是我們業務的圖片尺寸還不算太大,頁面中多花幾十毫秒也能接受,相比節省等待網絡的時間我們覺得這是更有利的。
于是我們準備在手機QQ H5業務中推廣SharpP格式,但推廣新圖片格式會帶來很大的應用成本。首先大部分的圖片鏈接都是寫死在代碼里面,而且頁面并不知道移動終端有沒有能力去解碼SharpP的格式。
難道H5頁面要針對不同的手機QQ版本去準備不同的HTML?或者圖片資源發布到CDN上時生成兩個不同格式的鏈接,然后在H5內部根據終端版本選擇不同的鏈接?這個開發成本當然是不可接受的。
除了圖片格式的問題,我們發現用戶的不同機型會存在流量浪費的情況。我們的UI設計通常都是針對iPhone6的屏幕尺寸做的,默認是750px的圖片素材。小屏幕的手機,比如640px和480px,同樣是下載750px的圖片,然后在渲染的時候進行縮小。
這樣實際浪費了非常大的帶寬,所以我們思考CDN是否能根據用戶手機屏幕尺寸來下發不同格式的圖片。
reshape架構
這種屏幕自適應的策略也面臨近似私有格式的成本,因為CDN也不知道手機的情況,最后我們提出了reshape的架構,從圖片下載完整的環節來看,大概可以分成4個層級:
- 最底層我們稱作CDN源站,這里我們部署了圖片格式轉換工具,業務方不需要care JPG制作出來后再生成sharpP還是WebP,只需要把圖片發布在CDN源站上就能自動轉成對應的格式和屏幕分辨率;
- 往上是用戶手機接入的CDN節點,部署全國各地用于加速和緩存文件的server。
- 我們和瀏覽器團隊做了合作,把sharpP的解碼格式放在瀏覽器內核中,這樣最上層的業務不需要關心當前的瀏覽器是否支持WebP還是sharpP。
在打開頁面的時候,WebView會自動帶上終端的屏幕尺寸以及支持哪些圖片格式給CDN節點,CDN節點再從源站獲取最新的圖片,源站這個時候有可能已經離線或實時生成好對應的圖片了。
拆開來看WebView這一層,除了集成sharpP的解碼庫之外,其他事情相對簡單,例如:
- 在請求header里面額外添加了字段,比如User-Agent里添加了“Pixel/750”,如果是480px的機器這個值就變成480;
- 在Accept里增加了sharpP的協議頭:image/sharpP
在源站里會存儲3*3數量的圖片,每一張業務圖片提交給源站發布的時候,都會生成9張圖片。CDN節點會根據WebView的請求,在回源的時候向CDN源站請求對應類型的圖片,但對于業務和WebView來看請求的還是同一個鏈接,這樣手機QQ所有的H5頁面都不需要任何一行前端代碼的修改,就能享受圖片格式所帶來的尺寸自適應和流量節省。
以下是更形象的過程,在Accept增加字段,然后返回對應的圖片:
這個技術并不復雜,我個人認為不存在太深的技術門檻,更多的是從客戶端、Web到CDN后臺這整個鏈條的打通。但過程中我們也踩了一些坑:我們在灰度的時候發現很多iOS用戶來投訴說頁面展示時圖片不能展示。
這個讓我們非常驚訝,因為當時還沒有把這項技術部署到iOS上,只是Android在應用。我們檢查了CDN的代碼也沒有問題,那為什么會把sharpP的圖片下發到iOS用戶呢?
后來分析發現,中國不同地區運營商之間,會做類似CDN Cache的緩存服務。當Android用戶第一次請求sharpP圖片的時候,運營商的server從我們的CDN拿到了sharpP格式鏈接。當緩存生效期間內,同一個地區其他iOS用戶上來請求時,運營商發現URL一樣,直接就把sharpP格式的圖片返回給iOS用戶。
這個問題是我們整體架構上沒有去全盤review而踩中的坑,HTTP有個標準的約定可以解決這種緩存問題。在CDN分發內容的時候,通過Vary字段指定緩存的時候要去參考Accept和User-Agent里的字段,我們把這個Vary加上之后問題基本解決了。
這個案例給了我們額外的啟發。我們現網中,Pixel字段有三種取值:480px、640px、750px。我們內部討論過是否可以把屏幕尺寸直接寫在User-Aagent里,這樣以后Android出了一些新的屏幕分辨率我們也能在后臺做更好的自適應,為每種機型去生成不同格式的圖片。
假如真的這么做的話,會給運營商和我們自己的CDN緩存帶來巨大的回源開銷。每個分辨率的圖片都要緩存一份,例如498px,中間運營商沒有這機型的緩存,就會到我們的服務去回源,這樣N個屏幕尺寸會給我們CDN帶來N倍的回源壓力。
數據以及效果
言歸正傳,最后數據效果也是比較明顯的,下圖是我們在Android灰度的效果數據。我們H5業務的圖片流量從40+GB下降了20+GB。對于騰訊來說20+GB的帶寬不是特別大的成本,但是在春節活動場景下,可以增加近一倍的業務空間。額外帶來的好處,是用戶看到頁面圖片所等待的時間相對縮減了,用戶側的流量也節省了一半。
H5快速運營時的穩定性
我們解決了頁面加載速度和流量消耗的問題時,也開始考慮H5在快速運營下的穩定性問題。相信前端開發都有遇到過某個頁面代碼一改,其他功能就不正常了的情況。采用hybrid開發很有可能native是要給JS頁面提供很多API的,客戶端小小的改動可能導致JS API受到影響,從而導致全網的H5頁面功能不正常。
除了功能穩定性之外還有一個很大的問題,我們每天都在發布前端頁面,那頁面的優化性能如何不被劣化?我們好不容易花了時間把頁面加載的性能降低到1秒,會不會有一些前端的修改比如引入更多的外鏈JS/CSS依賴導致整個頁面性能劣化?我們做了一些工具去解決這些問題。
Quick Test Automation
這是我們內部稱作快速自動化的工具。我們會把前端所有的測試用例集寫成自動化測試,然后每天都會把全網所有頁面所有的測試用例集跑一遍,檢查功能是否正常。
Web Performance Test
我們會對Web的性能做Web Performance Test的監控,這里我們首要觀察的是頁面每次打開所消耗的流量,因此會用工具去分析頁面中所有加載的圖片是不是有些可以轉成sharpP但仍然使用了JPG的。有了這套監控,能促使我們團隊之外的H5開發者去優化他們的頁面。
前端經常提到優化時要減少請求數量等等,這些可以認為是軍規的規則,我們都會在測試中進行監管。前面沒有詳細提到客戶端優化的一些方法,但是我們對于WebView在客戶端啟動的耗時也做了一些監控。
前端部署流程
我們還有更嚴格的前端發布流程,所有在測試環境中寫好的并且測試通過的代碼,如果要發布到正式環境必須要通過QTA和WPT的驗證,如果自動化測試成功率低于95%則不允許發布。
發布到正式環境之后,我們在外網還有綜合評分監控的系統,其首要監控的指標是關于速度的,我們把頁面打開的速度拆解為客戶端耗時、網絡耗時和頁面耗時并對它們分別監控。
我們每天都會輸出如下的監控報表來觀察每天速度變化,這里我們并不單純關心全網的性能怎么樣,我們更關心慢速用戶的體驗,例如大于5秒的用戶最近占比會有多少。
除了這些,H5經常遇到的某些JS報錯而導致頁面不正常,加載過慢導致用戶看到白屏的時間過長等等問題,我們對這些都有系統的監控。
集成運營體系
除了之前提到的內容之外我們還做了Debug平臺,許多調試能力已經提前部署在所有手機QQ終端。我們可以通過遠程命令去檢查用戶的DNS解析情況,命中了哪臺server,用戶是否受到運營商劫持等等。
寫在最后
整個QQHybrid的架構基本介紹完了,我們除了性能上的優化,也對CDN上的架構做了調整,也做了運營監控工具。我認為正是有了運營監控系統,才能讓我們整個H5和hybird團隊能放心大膽地修改頁面和發布新功能,同時保證穩定和可靠。
整個過程中也讓我們感到hybrid架構并不像以前大家理解的,只是客戶端和前端配合的工作就OK了,在整個架構體系中后臺技術也發揮了很大的作用。而CDN改造我們也請教了運維團隊的支持,QTA和WPT中也有測試開發團隊的參與。可以說整個體系的建立,是所有崗位并肩作戰的結果。
來自:http://www.iteye.com/news/32259