用hive来进行日志分析有一段时间了,这里简要记录下我使用UDF和存储与导出hsql结果的实现方式,以供参考。

(一)UDF 开发与使用案例

1、创建Maven工程,开发UDF(基于hadoop2.2.0+hive-0.12.0)。

org.apache.hadoop
hadoop-mapreduce-client-core
2.2.0
org.apache.hadoop
hadoop-common
2.2.0
org.apache.hadoop
hadoop-mapreduce-client-common
2.2.0
org.apache.hadoop
hadoop-mapreduce-client-jobclient
2.2.0
org.apache.hive
hive-exec
0.12.0

2、HIVE自定义函数(扩展UDF类并且实现evaluate函数即可)package com.test.yyting.hive.token;

import org.apache.hadoop.hive.ql.exec.UDF;
public class YYTingToken extends UDF{
public Long evaluate(String s)
{
try{
if(s==null)
{
return null;
}else{
return UCenterUtil.getUserIdByToken(s);
}
}catch(Exception e){
return null;
}
}
}

我这里的业务的解析全部定义在工具类UCenterUtil的静态方法getUserIdByToken(s)中去了,由于该方法只与业务相关,这里就不再特别描述了,在具体实现的时候,可以使用任何需要的业务方法或者工具方法来替换即可。

3、导出为Java包

利用MVN命令来将用户自定义函数相关Java代码打成jar包。

mvn install -Dmaven.test.skip=true -U

我这里导出的java包名为:yyting-token.jar

4、使用UDF

上传yyting-token.jar包到hive的所属的服务器中,我这里将它放置在/home/hadoop/hadoop-2.2.0/udf/目录下。

在hive的命令行中分别执行如下2条命令:

add jar /home/hadoop/hadoop-2.2.0/udf/yyting-token.jar;
CREATE TEMPORARY FUNCTION getUserIdByToken AS 'com.lazyaudio.yyting.hive.token.YYTingToken';

至此即可在hive中使用getUserIdByToken这个用户定义函数了。

我这里使用的hsql为(根据用户的token来计算不同的userId的个数,即日活跃用户数):

select count(distinct getUserIdByToken( parse_url(concat( 'http://yytingting.com',regexp_extract(request, '(\"[^ ]*) ([^ ]*) ([^ ]*\")', 2)), 'QUERY','token') ) )
from logs_app_nginx as a
where date=20140512 and status=='200';

(二)HIVE结果存储与导出到mysql

之前一段时间以来都是,手动执行一些hive脚本计算出结果来,再人工分析下,一直以来觉得这个太初级了,今天外面的太阳太大、太大,终于猫在家里,把这个自动化来实现一把了。

理想的情况:

每日自动执行HIVE的任务,将结果输出到Hive的表中,再将HIVE的表对应的结果导出到mysql中去,再利用开源图标工具来将统计结果以合理方式显示出来,以此来指导业务、与技术的变更。

恨不能一下就实现这个目标,苦于弄这个确实只是利用业务时间,一直只是缓慢的进展着啊,奈何!

我这里的业务案例为:每日自动计算各资源服务器的每小时下载平均速率

原来都是手动在Hive命令行中执行如下hsql,并且把结果COPY到EXCEL中去:

select resource,hosttype,host, stat_date,stat_hour ,round(avg(size/rt/1024),1) as avg_speed from (
select resource,hosttype,host, substr(time,2,11) as stat_date, substr(time,14,2) as stat_hour,rt,size
from logs_res_nginx as a
where rt>1 and size>1024 and date='20140524'
) a
group by resource,hosttype,host, stat_date,stat_hour
order by resource,hosttype,host, stat_date,stat_hour asc;

要实现我们目标,的做这么些事情:

(1)创建表t_res_download_speed来存储上述hsql的执行结果

CREATE TABLE t_res_download_speed(
resource string,
hosttype string,
host string,
stat_date string,
stat_hour string,
avg_speed string)
PARTITIONED BY (date string)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';

(2)每日定时执行类似如下的脚本来计算平均下载速率并且将结果存入表t_res_download_speed中去

INSERT OVERWRITE TABLE t_res_download_speed
PARTITION (date=20140524)
select resource,hosttype,host, stat_date,stat_hour ,round(avg(size/rt/1024),1) as avg_speed from (
select resource,hosttype,host, substr(time,2,11) as stat_date, substr(time,14,2) as stat_hour,rt,size
from logs_res_nginx as a
where rt>1 and size>1024 and date='20140524'
) a
group by resource,hosttype,host, stat_date,stat_hour
order by resource,hosttype,host, stat_date,stat_hour asc;

(3)利用sqoop将hive的表t_res_download_speed数据导入到mysql中去