本文由【友盟+】技術專家馬巍源、張永峯共同撰稿
隨着移動互聯網和大數據技術的發展,智能手機的普及,幾乎全部工做、學習、生活中的全部場景都離不開手機,手機 APP 已經取代了傳統的生活方式,讓人們能夠體驗便捷高效的服務,固然它也承載着大量豐富的信息,收集這些 APP 的數據,集中對數據進行清洗和分析,就能將這些海量數據變爲有價值的數據能源。數據採集是開發數據能源的第一步,如何採集數據,什麼樣的技術架構可以支持海量數據的採集、甄別和傳輸,這是本文須要討論的問題。緩存
與 PC 端不一樣,對於手機、iPad、智能手錶、電視盒子等移動設備,咱們觸達它們的載體就是 APP。原生 SDK 在多語言上支持上須要投入不少的開發資源,跨平臺應用開發漸成趨勢,但 JS SDK 在各框架上的實現也各有差別,所以,目前移動採集 SDK 在對多平臺、多語言的支持上難度較大。 安全
難度更大的是對 Android 設備的機型適配問題。因爲 Android 系統的開源特性,各廠商爲了在各家機型上有更好的用戶體驗,都有針對性的作了 ROM 改良,尤爲近些年 Android 在虛擬機、編譯器上的改動較大,這就給機型適配帶來更大的難度。爲了避免給 APP 帶來卡頓、閃退、黑屏、崩潰、加載速度慢等差的體驗,還須要支持開發者各類異常方式的接口調用,須要有極強的容錯性。服務器
移動端的流量在持續的增加,【友盟+】在移動端覆蓋的 APP 超過 135 萬款,覆蓋全球移動設備日活躍數超過 14 億個,天天處理的數據量達 280 億,龐大的數據天天都在考驗着咱們的採集 SDK 和服務端的承載能力,【友盟+】在移動端採集技術上不斷更新迭代,持續多年保持市場覆蓋領先的地位。網絡
咱們最初 SDK 的設計思想是簡單高效,所以在 SDK 端沒有任何對數據預處理的邏輯,甚至緩存策略也很是簡單,全部實時產生的數據都會實時上報服務器。但隨着移動端流量的暴漲,這種高併發的請求對服務器帶來很大的壓力。下圖是 1.0 版本的通訊協議。架構
因而考慮經過控制發送頻率來減少併發,開發者能夠根據業務須要採用不一樣的發送策略:啓動、間隔、退出發送,而且在【友盟+】平臺可隨時變動。雖然有效減少了服務端的壓力,但又帶來了另外一個問題,單條數據的包體大小有可能超過 request-body 的上限,致使請求超時。而且流量壓力一樣是須要亟待解決的問題,因而,在 2.0 版本上咱們對數據進行了壓縮,並增長了安全機制。服務端增長了數據預處理的邏輯,完善了對數據的校驗。併發
只能單向通訊的協議是不靈活的,有不少時候咱們須要 SDK 的行爲進行一些控制,好比發送策略的修改、屏蔽錯誤埋點數據,或者發現數據被污染決定拋棄,這些操做服務器須要通知到 SDK,而且在沒有長鏈接的狀況下該怎麼作。在 3.0 版本上咱們把 http 請求的 response 的信息包體設計控制語義,SDK 除了從 response 得到服務器的接收狀態,同時能夠得到服務器的控制指令,從而實現服務器想要獲得的效果。框架
若是每一條 Log 都必須等待並解析服務器返回的控制信息,顯然服務器對數據處理的時效性和併發處理能力會大大折損,而且有些業務數據其實無需解析並執行這些控制信息。所以,咱們對業務數據進行了精細的分解,一些業務數據使用雙向通訊協議,可以解析並執行控制指令,其他的業務數據屬於狀態無關數據,仍然使用單向通訊協議。異步
那麼將來其實還能夠將控制協議與業務傳輸協議分離,各自使用不一樣的發送頻率,但又能保證全部業務數據是受服務器指令控制的。高併發
移動數據採集 SDK 架構主要由三部分組成:用戶接口、業務模塊和控制模塊。組件化
咱們能夠從幾個場景的時序圖來解析這幾個模塊的工做原理。
用戶啓動 App 的時候,實際上是觸發了開發者調用的初始化接口,Service Moudle 和 Control Moudle 會異步的進行一些初始化的操做:建立 Session、加載設備信息等。
當用戶在 APP 中有點擊、滑動屏幕的行爲,會觸發開發者在 APP 中預設置埋點事件。
Servie Moudle 會生成相應的事件數據,調用 Control Moudle 的接口檢查發送策略和安全策略,以後 Servie Moudle 會將事件數據放到緩存隊裏中待發送。
不管用戶退出 APP 後,SDK 還會在短暫的瞬間完成不少操做:結束 Session、持久化保存數據,在 iOS 中還會直接完成數據封裝、打包、上報的工做。
咱們提供的產品功能愈來愈多,業務場景愈來愈複雜,爲了知足各類各樣的解決方案的需求,SDK 須要爲各個業務場景維護多個分支、多個版本,開發資源浪費、版本迭代週期拉長,爲了解決這個問題,咱們必需要設計一個靈活的架構,使每一個產品功能變成可自由組合、拆卸的組件。
組件化將統一約定 package 和 public API 的文件規範。針對當前【友盟+】業務的需求,創建標準的 SDK 產品公共庫(如:network,serialize,configure,cache 等),組件化結構分爲兩部分,Common 將做爲一個獨立的 library package,而 Component 中每一個產品做爲獨立 library。
其結構以下:
組件的劃分的顆粒度,能夠根據業務需求,咱們的設計是根據產品,或者業務來劃分組件。一個產品可能包含不少功能,好比統計產品包含事件數據採集、錯誤數據採集、A/B Test 等功能,Push 產品包含消息推送和應用內消息,在某些場景下,可能有些開發者會只使用部分功能,好比,只用錯誤分析功能和 Push 的消息推送,那麼組件顆粒細化到功能層,就會更加靈活,可知足更多場景的需求,而且體積的減少是對開發者來講是很是有吸引力的。
組件化的架構改變了之前業務邏輯與基礎功能深度耦合的情況,業務開發人員能夠專一於業務邏輯的實現,而不須要考慮如網絡通訊、消息隊列管理、設備信息採集等基礎功能的實現。業務邏輯代碼的任何改動,不會影響基礎功能邏輯,增強了代碼的健壯性,同時在迴歸測試周期上也大大縮短。
【友盟+】數據採集技術將持續的適應業務場景的變化,將來咱們的目標是讓咱們的 SDK 更加智能,更加安全,讓企業及開發者集成更加簡單、數據更加精準。