本文的主角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