本文的主角Aviator,是一個高性能、輕量級的基於java實現的表達式引擎,它動態地將String類型的表達式編譯成Java ByteCode並交給JVM執行。
Aviator支持全部的關係運算符和算術運算符,不支持位運算,同時支持表達式的優先級,優先級跟Java的運算符同樣,而且支持經過括號來強制優先級。css
Aviator很適合PV、UV的計算。它比Drools輕量,執行效率高,比正則表達式的表達能力強。靈活運用Aviator能夠使得不少數據統計的代碼變得更通用。java
通常來講,常見的PV和UV的統計,都是以下的計算流程:正則表達式
在Map階段:數據庫
一、過濾掉不符合條件的數據app
二、符合條件的數據輸出key,1性能
在Reduce階段:.net
一、要麼累加,要麼求平均設計
以上的三個步驟中,Map階段的兩個步驟能夠經過Aviator腳本變成動態的,Map的第二個階段輸出的數據的Value能夠設計爲固定格式的,例如:{pv,通常爲1}|{響應時間}|{ip},那麼Reduce階段的一個步驟就能夠計算出來PV、UV和平均響應時間。舉幾個栗子:日誌
例子一、排除.css,.js和.png後綴的請求以後,計算應用的PV,UVip
Map階段:
a、按照以下規則過濾: (row[keyMap.uri] =~ /.*\.css/) && (row[keyMap.uri] =~ /.*\.js/) && ((row[keyMap.uri] =~ /.*\.png/))
b、輸出:pv|app|{擴展名字},1|20|{IP}
Reduce階段:
a、累加獲得PV,{IP}放入Map,Map的size即爲UV
例子二、排除.css,.js和.png後綴的請求以後,計算各個HTTP Status Code的PV
Map階段:
a、按照以下規則過濾: (row[keyMap.uri] =~ /.*\.css/) && (row[keyMap.uri] =~ /.*\.js/) && ((row[keyMap.uri] =~ /.*\.png/))
b、輸出:pv|app|row[keyMap.status],1|20|{IP}。其中row[keyMap.status]是用於動態地從一行日誌數據中取值的Aviator腳本
Reduce階段:
a、累加獲得PV,{IP}放入Map,Map的size即爲UV
基於以上的設計,再加幾個配套的數據庫表,就能夠實現一個MR計算n種規則的PV、UV和平均響應時間了。
P.S. 有興趣的話,能夠琢磨一下平均響應時間如何計算 :D