Nutch 2.0 之 Apache Gora MR介绍

Nutch 2.0 之 Apache Gora MR介绍
-----------------


1. 介绍

  Apapche Gora内建了对于Apache Hadoop的支持,而Gora的dataStore可以用来做为InputFormat与OutputFormat的输入与输出,然而这些输出的对象都会被序列化,Gora扩展了Avro的DatumWriters来实现的。


2. 一个简单的例子



  下面是gora-tutorial中的一个简单的例子来说明Gora MR的用法,这个例子是使用了上一个例子的输出,作为其输入,用MR来分析日志的信息,用于统计单个URL一天之中的访问量,然后把分析后的结果写回HBase中的一个例子,当然,你也可以把输出写回SQL或者虽的数据库中,这个例子可以在t gora-tutorial/src/main/java/org/apache/gora/tutorial/log/LogAnalytics.java找到。


  为了对日志数据进行分析,mapper方法以pageview为输入,输出的Key为<URL,timestamp>对,Value为1,表示一次,在reducer中对相同key的value进行聚合,得到一个总数,然后生成一个MetricDatum对象,把这个对象序列化到数据库中去。


  数据模型的定义,这里我们用到了MetricDatum这个对象,它的定义在gora-tutorial/src/main/avro/metricdatum.json,我们要用bin/gora compile来产生它的一个java文件,


json的定义文件如下:
[html]  view plain copy
  1. {  
  2.   "type": "record",  
  3.   "name": "MetricDatum",  
  4.   "namespace": "org.apache.gora.tutorial.log.generated",  
  5.   "fields" : [  
  6.     {"name": "metricDimension", "type": "string"},  
  7.     {"name": "timestamp", "type": "long"},  
  8.     {"name": "metric", "type" : "long"}  
  9.   ]  
  10. }  




   我们可以看到,它的类型为record, 名称空间为org.apache.gora.tutorial.log.generated,还有三个字段,分别定义了字段名与类型。


  下面我们还要定义datastore的一个映射文件,内容如下:
  
[html]  view plain copy
  1. <class name="org.apache.gora.tutorial.log.generated.MetricDatum" keyClass="java.lang.String" table="Metrics">  
  2.     <field name="metricDimension" family="common"  qualifier="metricDimension"/>  
  3.     <field name="timestamp" family="common" qualifier="ts"/>  
  4.     <field name="metric" family="common" qualifier="metric"/>  
  5.   </class>  

  
  我们可以看到,在class中定义了类名,key的类型,还有表名Metrics。在field中定义了相应的字段名,family还有qualifier。


  好了,下面我们来命令这个MR程式,输入如下命令:

[html]  view plain copy
  1. $ bin/gora loganalytics  

  有一些输入,部分如下:

[html]  view plain copy
  1. 12/07/21 13:35:16 INFO mapreduce.GoraRecordWriter: gora.buffer.write.limit = 10000  
  2. 12/07/21 13:35:17 INFO mapred.TaskRunner: Task:attempt_local_0001_r_000000_0 is done. And is in the process of commiting  
  3. 12/07/21 13:35:17 INFO mapred.LocalJobRunner: reduce > reduce  
  4. 12/07/21 13:35:17 INFO mapred.TaskRunner: Task 'attempt_local_0001_r_000000_0' done.  
  5. 12/07/21 13:35:17 INFO mapred.JobClient:  map 100% reduce 100%  
  6. 12/07/21 13:35:17 INFO mapred.JobClient: Job complete: job_local_0001  
  7. 12/07/21 13:35:17 INFO mapred.JobClient: Counters: 12  
  8. 12/07/21 13:35:17 INFO mapred.JobClient:   FileSystemCounters  
  9. 12/07/21 13:35:17 INFO mapred.JobClient:     FILE_BYTES_READ=561645  
  10. 12/07/21 13:35:17 INFO mapred.JobClient:     FILE_BYTES_WRITTEN=1126606  
  11. 12/07/21 13:35:17 INFO mapred.JobClient:   Map-Reduce Framework  
  12. 12/07/21 13:35:17 INFO mapred.JobClient:     Reduce input groups=3033  
  13. 12/07/21 13:35:17 INFO mapred.JobClient:     Combine output records=0  
  14. 12/07/21 13:35:17 INFO mapred.JobClient:     Map input records=10000  
  15. 12/07/21 13:35:17 INFO mapred.JobClient:     Reduce shuffle bytes=0  
  16. 12/07/21 13:35:17 INFO mapred.JobClient:     Reduce output records=3033  
  17. 12/07/21 13:35:17 INFO mapred.JobClient:     Spilled Records=20000  
  18. 12/07/21 13:35:17 INFO mapred.JobClient:     Map output bytes=512510  
  19. 12/07/21 13:35:17 INFO mapred.JobClient:     Combine input records=0  
  20. 12/07/21 13:35:17 INFO mapred.JobClient:     Map output records=10000  
  21. 12/07/21 13:35:17 INFO mapred.JobClient:     Reduce input records=10000  
  22. 12/07/21 13:35:17 INFO log.LogAnalytics: Log completed with success  


完成以后可以查看一下HBase的Metrics表,使用如下命令

[html]  view plain copy
  1. hbase(main):007:0> scan 'Metrics' ,{LIMIT=>1}    
  2. ROW                              COLUMN+CELL                                                                                     
  3.  /?a=1__-znawtuabsy&k=96804_1236 column=common:metric, timestamp=1342848916670value=\x00\x00\x00\x00\x00\x00\x00\x09           
  4.  902400000                                                                                                                       
  5.  /?a=1__-znawtuabsy&k=96804_1236 column=common:metricDimension, timestamp=1342848916670value=/?a=1__-znawtuabsy&k=96804        
  6.  902400000                                                                                                                       
  7.  /?a=1__-znawtuabsy&k=96804_1236 column=common:ts, timestamp=1342848916670value=\x00\x00\x01\x1F\xFD \xD0\x00                  
  8.  902400000                                                                                                                       
  9. 1 row(s) in 0.0200 seconds  

我们已经可以看到分析后的数据已经存储到Metrics表中了。


3. 程式代码分析



   在定义Hadoop的任务的时候,我们可以选择是否使用Gora来做为其输入与输出, Gora定义了自己的GoraInputFormat 与GoraOutputFormat,而且Gora还定义自己的GoraMapper与GoraReducer类,提供一些方法的初始化静态方法 。在下面的代码中,就使用了Gora(Mapper|reducer)的一些静态方法来进行初始始化。下面是Job初始化代码:
[java]  view plain copy
  1.  public Job createJob(DataStore<Long, Pageview> inStore  
  2.   , DataStore<String, MetricDatum> outStore, int numReducer) throws IOException {  
  3. Job job = new Job(getConf());  
  4.   
  5.   
  6. job.setJobName("Log Analytics");  
  7. job.setNumReduceTasks(numReducer);  
  8. job.setJarByClass(getClass());  
  9.   
  10.   
  11. /* Mappers are initialized with GoraMapper.initMapper() or  
  12.  * GoraInputFormat.setInput()*/  
  13. GoraMapper.initMapperJob(job, inStore, TextLong.class, LongWritable.class  
  14.     , LogAnalyticsMapper.classtrue);  
  15.   
  16.   
  17. /* Reducers are initialized with GoraReducer#initReducer(). 
  18.  * If the output is not to be persisted via Gora, any reducer  
  19.  * can be used instead. */  
  20. GoraReducer.initReducerJob(job, outStore, LogAnalyticsReducer.class);  
  21.   
  22. return job;  
  23.   
  24.       


  下面是它的run函数的代码:

[java]  view plain copy
  1.   @Override  
  2.  public int run(String[] args) throws Exception {  
  3.      
  4.    DataStore<Long, Pageview> inStore;  
  5.    DataStore<String, MetricDatum> outStore;  
  6.    Configuration conf = new Configuration();      
  7.   
  8.   
  9.    if(args.length > 0) {  
  10.      String dataStoreClass = args[0];  
  11.      inStore = DataStoreFactory.  
  12.          getDataStore(dataStoreClass, Long.class, Pageview.class, conf);  
  13.      if(args.length > 1) {  
  14.        dataStoreClass = args[1];  
  15.      }  
  16.      outStore = DataStoreFactory.  
  17.          getDataStore(dataStoreClass,   
  18.          String.class, MetricDatum.class, conf);  
  19.    } else {  
  20. inStore = DataStoreFactory.getDataStore(Long.class, Pageview.class, conf);  
  21. outStore = DataStoreFactory.getDataStore(String.class, MetricDatum.class, conf);  
  22.    }  
  23.      
  24.    Job job = createJob(inStore, outStore, 3);  
  25.    boolean success = job.waitForCompletion(true);  
  26.      
  27.    inStore.close();  
  28.    outStore.close();  
  29.      
  30.    log.info("Log completed with " + (success ? "success" : "failure"));  
  31.      
  32.    return success ? 0 : 1;  
  33.  }  


  我们可以看到,生成两个输入与输出的dataStore。


  下来看一下自定义的LogAnalyticsMapper代码,它扩展自GoraMapper,它的输入为<Long,Pageview>,部分代码如下:

[java]  view plain copy
  1.  private TextLong tuple;  
  2.   
  3.   
  4. protected void map(Long key, Pageview pageview, Context context)   
  5.   throws IOException ,InterruptedException {  
  6.     
  7.   Utf8 url = pageview.getUrl();  
  8.   long day = getDay(pageview.getTimestamp());  
  9.     
  10.   tuple.getKey().set(url.toString());  
  11.   tuple.getValue().set(day);  
  12.     
  13.   context.write(tuple, one);  
  14. };  


而LogAnalyticsReducer也扩展自GoraReducer,部分代码如下:


[java]  view plain copy
  1.  protected void reduce(TextLong tuple  
  2.     , Iterable<LongWritable> values, Context context)   
  3.   throws IOException ,InterruptedException {  
  4.     
  5.   long sum = 0L; //sum up the values  
  6.   for(LongWritable value: values) {  
  7.     sum+= value.get();  
  8.   }  
  9.     
  10.   String dimension = tuple.getKey().toString();  
  11.   long timestamp = tuple.getValue().get();  
  12.     
  13.   metricDatum.setMetricDimension(new Utf8(dimension));  
  14.   metricDatum.setTimestamp(timestamp);  
  15.     
  16.   String key = metricDatum.getMetricDimension().toString();  
  17.   metricDatum.setMetric(sum);  
  18.     
  19.   context.write(key, metricDatum);  
  20. };  



我们可以看到,它输出的Value类型是metricDatum,这个就是我们之前在json中定义的数据模型,它会被序列化到数据库中去。

4. 参考

http://gora.apache.org/docs/current/tutorial.html


转载   :http://blog.csdn.net/amuseme_lu/article/details/7770424

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值