1、攜程實時用戶數據採集系統設計實踐
隨着移動互聯網的興起,特別是近年來,智能手機、pad等移動設備憑藉便捷、高效的特色風靡全球,同時各種APP的快速發展進一步下降了移動互聯網的接入門檻,愈來愈多的網民開始從傳統PC轉移至移動終端上。但傳統的基於PC網站和訪問日誌的用戶數據採集系統已經沒法知足實時分析用戶行爲、實時統計流量屬性和基於位置服務(LBS)等方面的需求。
咱們針對傳統用戶數據採集系統在實時性、吞吐量、終端覆蓋率等方面的不足,分析了在移動互聯網流量劇增的背景下,用戶數據採集系統的需求,研究在多種訪問終端和多種網絡類型的場景下,用戶數據實時、高效採集的方法,並在此基礎上設計和實現實時、有序和健壯的用戶數據採集系統。此係統基於Java NIO網絡通訊框架(Netty)和分佈式消息隊列(Kafka)存儲框架實現,其具備實時性、高吞吐、通用性好等優勢。
一、技術選型和設計方案
一個典型的數據採集分析統計平臺,對數據的處理,主要由以下五個步驟組成:
圖1 數據平臺處理流程
其中,數據採集步驟是最核心的問題,數據採集是否豐富、準確和實時,都直接影響整個數據分析平臺的應用的效果。本論文關注的步驟主要在數據採集、數據傳輸和數據建模存儲這三部分。
爲知足數據採集服務實時、高效性、高吞吐量和安全性等方面的要求,同時能借鑑互聯網大數據行業一些優秀開源的解決方案,因此整個系統都將基於Java技術棧進行設計和實現。整個數據採集分析平臺系統架構以下圖所示:
圖2 數據採集分析平臺系統架構
其中整個平臺系統主要包括以上五部分:客戶端數據採集SDK以Http(s)/Tcp/Udp協議根據不一樣的網絡環境按必定策略將數據發送到Mechanic(UBT-Collector)服務器。服務器對採集的數據進行一系列處理以後將數據異步寫入Hermes(Kafka)分佈式消息隊列系統。爲了關聯業務服務端用戶業務操做埋點、日誌,業務服務器須要獲取由客戶端SDK統一輩子成的用戶標識(C-GUID),而後業務服務器將用戶業務操做埋點、日誌信息以異步方式寫入Hermes(Kafka)隊列。最後數據消費分析平臺,都從Hermes(Kafka)中消費採集數據,進行數據實時或者離線分析。其中Mechanic(UBT-Collector)系統還包括對採集數據和自身系統的監控,這些監控信息先寫入Hbase集羣,而後經過Dashboard界面進行實時監控。
(1)基於NIO的Netty網絡框架方案
要知足前面提到的高吞吐、高併發和多協議支持等方面的要求。咱們調研了幾種開源異步IO網絡服務組件(如Netty、MINI、xSocket),用它們和Nginx Web服務器進行了性能對比,決定採用Netty做爲採集服務網絡組件。下面對它進行一些概要介紹:Netty是一個高性能、異步事件驅動的NIO框架,它提供了對TCP、UDP和文件傳輸的支持,Netty的全部IO操做都是異步非阻塞的,經過Future-Listener機制,用戶能夠方便的主動獲取或者經過通知機制得到IO操做結果。
圖3 Netty框架內部組件邏輯結構
Netty的優勢有:
功能豐富,內置了多種數據編解碼功能、支持多種網絡協議。
高性能,經過與其它主流NIO網絡框架對比,它的綜合性能最佳。
可擴展性好,可經過它提供的ChannelHandler組件對網絡通訊方面進行靈活擴展。
易用性,API使用簡單。
通過了許多商業應用的考驗,在互聯網、網絡遊戲、大數據、電信軟件等衆多行業獲得成功商用。
Netty採用了典型的三層網絡架構進行設計,邏輯架構圖以下:
圖4 Netty三層網絡邏輯架構
第一層:Reactor通訊調度層。該層的主要職責就是監聽網絡的鏈接和讀寫操做,負責將網絡層的數據讀取到內存緩衝區中,而後觸發各類網絡事件,例如鏈接建立、鏈接激活、讀事件、寫事件等,將這些事件觸發到Pipeline中,再由Pipeline充當的職責鏈來進行後續的處理
第二層:職責鏈Pipeline層。負責事件在職責鏈中有序的向前(後)傳播,同時負責動態的編排職責鏈。Pipeline能夠選擇監聽和處理本身關心的事件。
第三層:業務邏輯處理層,通常可分爲兩類:a. 純粹的業務邏輯處理,例如日誌、訂單處理。b. 應用層協議管理,例如HTTP(S)協議、FTP協議等。
咱們都知道影響網絡服務通訊性能的主要因素有:網絡I/O模型、線程(進程)調度模型和數據序列化方式。
在網絡I/O模型方面,Netty採用基於非阻塞I/O的實現,底層依賴的是JDK NIO框架的Selector。
在線程調度模型方面,Netty採用Reactor線程模型。經常使用的Reactor線程模型有三種,分別是:
Reactor單線程模型:Reactor單線程模型,指的是全部的I/O操做都在同一個NIO線程上面完成。對於一些小容量應用場景,可使用單線程模型。
Reactor多線程模型:Rector多線程模型與單線程模型最大的區別就是有一組NIO線程處理I/O操做。主要用於高併發、大業務量場景。
主從Reactor多線程模型:主從Reactor線程模型的特色是服務端用於接收客戶端鏈接的再也不是一個單獨的NIO線程,而是一個獨立的NIO線程池。利用主從NIO線程模型,能夠解決一個服務端監聽線程沒法有效處理全部客戶端鏈接的性能不足問題。Netty線程模型並不是固定不變的,它能夠支持三種Reactor線程模型。
在數據序列化方面,影響序列化性能的主要因素有:
序列化後的碼流大小(網絡帶寬佔用)。
序列化和反序列化操做的性能(CPU資源佔用)。
併發調用時的性能表現:穩定性、線性增加等。
Netty默認提供了對Google Protobuf二進制序列化框架的支持,但經過擴展Netty的編解碼接口,能夠實現其它的高性能序列化框架,例如Avro、Thrift的壓縮二進制編解碼框架。
經過對Netty網絡框架的分析研究以及對比測試(見後面的可行性分析測試報告)可判斷,基於Netty的數據採集方案能解決高數據吞吐量和數據實時收集的難點。
(2)客戶端數據加解密和壓縮方案
對一些明感的採集數據,須要在數據傳輸過程當中進行加密處理。目前存在的問題是,客戶端採集代碼比較容易被匿名用戶獲取並反編譯(例如Android、JavaScript),致使數據加密的算法和密鑰被用戶竊取,較難保證數據的安全性。根據加密結果是否能夠被解密,算法能夠分爲可逆加密和不可逆加密(單向加密)。具體的分類結構以下:
圖5 加密算法分類
密鑰:對於可逆加密,密鑰是加密解算法中的一個參數,對稱加密對應的加解密密鑰是相同的;非對稱加密對應的密鑰分爲公鑰和私鑰,公鑰用於加密,私鑰用於解密。私鑰是不公開不傳送的,僅僅由通訊雙方持有保留;而公鑰是能夠公開傳送的。非對稱密鑰還提供一種功能,即數字簽名。經過私鑰進行簽名,公鑰進行認證,達到身份認證的目的。
根據數據採集客戶端的特色,對於採集數據使用對稱加密算法是很明智的選擇,關鍵是要保證對稱密鑰的安全性。目前考慮的方案主要有:
將加解密密鑰放入APP中某些編譯好的so文件中,若是是JavaScript採集的話,構造一個用C編寫的算法用於生成密鑰,而後藉助Emscripten把C代碼轉化爲JavaScript代碼,這種方案有較好的混淆做用,讓竊聽者不太容易獲取到對稱密鑰。
將密鑰保存到服務器端,每次發送數據前,經過HTTPS的方式獲取加密密鑰,而後對採集數據進行加密和發送。
客戶端和服務器端保存一份公鑰,客戶端生成一個對稱密鑰K(具備隨機性和時效性),使用公鑰加密客戶端通訊認證內容(UID+K),併發送到服務器端,服務端收到通訊認證請求,使用私鑰進行解密,獲取到UID和對稱密鑰K,後面每次採集的數據都用客戶端內存中的K進行加密,服務器端根據UID找到對應的對稱密鑰K,進行數據解密。
這三種客戶端數據加密方式基本能解決客戶端採集數據傳輸的安全性難題。
採集數據壓縮。爲了節省流量和帶寬,高效發送客戶端採集的數據,須要使用快速且高壓縮比的壓縮算法,目前考慮使用標準的GZIP和定製的LZ77算法。
(3)基於攜程分佈式消息中間件Hermes的數據存儲方案
Hermes是基於開源的消息中間件Kafka且由攜程自主設計研發。總體架構如圖:
圖6 Hermes消息隊列總體架構
Hermes消息隊列存儲有三種類型:
MySQL適用於消息量中等及如下,對消息治理有較高要求的場景。
Kafka適用於消息量大的場景。
Broker分佈式文件存儲(擴展Kafka、定製存儲功能)。
因爲數據採集服務的消息量很是大,因此採集數據須要存儲到Kafka中。Kafka是一種分佈式的,基於發佈/訂閱的消息系統。它能知足採集服務高吞吐量、高併發和實時數據分析的要求。它有以下優秀的特性:
以時間複雜度爲O(1)的方式提供消息持久化能力,即便對TB級以上數據也能保證常數時間複雜度的訪問性能。
高吞吐率。即便在很是廉價的商用機器上也能作到單機支持每秒100K條以上消息的傳輸。
支持Kafka Server間的消息分區,及分佈式消費,同時保證每一個Partition內的消息順序傳輸。
同時支持離線數據處理和實時數據處理。
Scale out,即支持在線水平擴展。
一個典型的Kafka集羣中包含若干Producer(能夠是Web前端產生的採集數據,或者是服務器日誌,系統CPU、Memory等),若干broker(Kafka支持水平擴展,通常broker數量越多,集羣吞吐率越高),若干Consumer Group,以及一Zookeeper集羣。Kafka經過Zookeeper管理集羣配置,選舉leader,以及在Consumer Group發生變化時進行rebalance。Producer使用push模式將消息發佈到broker,Consumer使用pull模式從broker訂閱並消費消息。Kafka拓撲結構圖以下:
圖7 Kafka拓撲結構
咱們知道,客戶端用戶數據的有序性採集和存儲對後面的數據消費和分析很是的重要,可是在一個分佈式環境下,要保證消息的有序性是很是困難的,而Kafka消息隊列雖然不能保證消息的全局有序性,但能保證每個Partition內的消息是有序的。在用戶數據採集和分析的系統中,咱們主要關注的是同一個用戶的數據是否能保證有序,若是咱們在數據採集服務端能將同一個用戶的數據存儲到Kafka的同一個Partition中,那麼就能保證同一個用戶的數據是有序的,所以基本上能解決採集數據的有序性。
(4)基於Avro格式的數據災備存儲方案
當出現網絡嚴重中斷或者Hermes(Kafka)消息隊列故障狀況下,用戶數據須要進行災備存儲,目前考慮的方案是基於Avro格式的本地文件存儲。其中Avro是一個數據序列化反序列化框架,它能夠將數據結構或對象轉化成便於存儲或傳輸的格式,Avro設計之初就用來支持數據密集型應用,適合於遠程或本地大規模數據的存儲和交換。
Avro定義了一個簡單的對象容器文件格式。一個文件對應一個模式,全部存儲在文件中的對象都是根據模式寫入的。對象按照塊進行存儲,在塊之間採用了同步記號,塊能夠採用壓縮的方式存儲。一個文件由兩部分組成:文件頭和一個或者多個文件數據塊。其存儲結構以下圖所示:
圖8 Avro對象容器文件格式
災備存儲處理過程是:當網絡異常或者Hermes(Kafka)消息隊列出現故障時,將採集的用戶數據解析並轉化成Avro格式後,直接序列化存儲到本地磁盤文件中,數據按Kafka-Topic分紅多個文件存儲,且每小時自動生成一個新的文件。當網絡或者Hermes(Kafka)故障恢復後,後端線程自動讀取磁盤Avro文件,將數據寫入Hermes(Kafka)消息隊列的對應Topic和分區中。每一個文件寫入成功後,自動刪除災備存儲文件。這樣能增長用戶數據採集服務的健壯性和加強服務容錯性。
二、架構設計方案可行性分析
在相同配置的測試服務器上(包括數據採集服務器、Hermes(Kafka)集羣)作以下對比實驗測試:(使用ApacheBenchmark進行Web性能壓力測試工具)
(1)Netty VS Nginx處理網絡請求對比
在不對採集數據進行業務處理的狀況下(即只接請求並作響應,不作業務處理,也不存儲採集數據),在5000併發,Keepalive模式下均能達到每秒處理4萬多請求,其中Nginx的CPU、內存消耗會小一些。測試對比數據以下:( ab參數: -k –n 10000000 –c 5000)
(2)Netty對採集數據進行業務處理
Netty服務加上採集數據解析相關業務處理,以及處理後的數據寫入Hermes(Kafka)消息隊列。能夠進行簡單的間接估算。若是採集服務要求達到:每秒處理3萬左右請求,99%的請求完成時間小於800ms的目標,則採集數據解析和存儲流程的處理時間必須在600ms之內。而這兩步又分爲數據解析和數據存儲,能夠分別進行壓力測試加以驗證。 根據咱們的壓力測試,採集數據解析和存儲也能徹底知足性能要求。
經以上對比實驗測試代表,使用Netty服務組件收集、解析數據並直接寫入Hermes(Kafka)分佈式消息隊列的方案初步具有可行性。
2、相關數據分析產品介紹
基於實時採集到的用戶數據和系統監控數據,咱們開發了一套相關的數據分析產品。產品的內容主要分如下幾部分:(1)、API和頁面性能報表;(2)、頁面訪問和流量;(3)、用戶行爲分析;(4)、系統異常崩潰分析;(5)、數據實時查詢工具;(6)、採集數據排障工具;(7)、其它。其中詳細分類以下圖所示:
圖9 數據分析產品分類
現選取其中幾個比較常見的產品作下簡單介紹:
一、單用戶瀏覽跟蹤
做用:實時跟蹤用戶瀏覽記錄,幫助產品優化頁面訪問流程、幫助用戶排障定位問題。
使用案例:根據用戶在客戶端上的惟一標識ID,如:手機號、Email、註冊用戶名、ClientId、VisitorId等查詢此用戶在某一時間段順序瀏覽過的頁面和每一個頁面的訪問時間及頁面停留時長等信息。若是用戶在瀏覽頁面過程當中發生了異常崩潰退出狀況,能夠結合應用崩潰信息關聯查詢到相關信息。
二、頁面轉化率
做用:實時查看各個頁面的訪問量和轉化狀況,幫助分析頁面用戶體驗以及頁面佈局問題。
使用案例:用戶首先配置頁面瀏覽路徑,如p1023 -> p1201 -> p1137 -> p1300,而後根據用戶配置頁面瀏覽路徑查詢某個時間段各個頁面的轉化率狀況。若有1.4萬用戶進入p1023頁面,下一步有1400用戶進入下一頁面p1201。這樣可推算出頁面p1201的轉化率爲10%左右。這是最簡單的一種頁面轉化率,還有間接的頁面轉化率,即只匹配第一個和最後一個頁面的訪問量。同時能夠按各類維度進行條件篩選,好比:網絡、運營商、國家、地區、城市、設備、操做系統等等。
三、用戶訪問流
做用:瞭解每一個頁面的相對用戶量、各個頁面間的相對流量和退出率、瞭解各維度下頁面的相對流量。
使用案例:用戶選擇查詢維度和時間段進行查詢,就能獲取到應用從第一個頁面到第N個頁面的訪問路徑中,每一個頁面的訪問量和獨立用戶會話數、每一個頁面的用戶流向、每一個頁面的用戶流失量等信息。
四、點擊熱力圖
做用:發現用戶常常點擊的模塊或者區域,判斷用戶喜愛、分析頁面中哪些區域或者模塊有較高的有效點擊數、應用於A/B測試,比較不一樣頁面的點擊分佈狀況、幫助改進頁面交互和用戶體驗。
使用案例:點擊熱力圖查看工具包括Web和APP端,統計的指標包括:原始點擊數(當前選中元素的原始點擊總數)、頁面瀏覽點擊數(當前選中元素的有效點擊數,同一次頁面瀏覽,屢次點擊累計算1次點擊)、獨立訪客點擊數(當前選中元素的有效點擊數, 同一用戶,屢次點擊累計算1次點擊)。
五、採集數據驗證測試
做用:快速測試是否能正常採集數據、數據量是否正常、採集的數據是否知足需求等。
使用案例:用戶使用攜程APP掃描工具頁面的二維碼,獲取用戶標識信息,以後正常使用攜程APP過程當中,能實時地將採集到的數據分類展現在工具頁面中,對數據進行對比測試驗證。
六、系統性能報表
做用:監控系統各業務服務調用性能(如SOA服務、RPC調用等)、頁面加載性能、APP啓動時間、LBS定位服務、Native-Crash佔比、JavaScript錯誤佔比等。按小時統計各服務調用耗時、成功率、調用次數等報表信息。
基於前端多平臺(包括iOS、Android、Web、Hybrid、RN、小程序)數據採集SDK的豐富的自動化埋點數據,咱們能夠對數據、用戶、系統三方面進行多維度立體的分析。服務於系統產品和用戶體驗、用戶留存、轉換率及吸引新用戶。前端