Nutch2.0 之 Apache Gora 介绍

来源:互联网 发布:赚佣金的软件 编辑:程序博客网 时间:2024/05/17 02:58
Nutch 2.0  之 Apache Gora介绍

-----------------


1. 什么是Apache Gora

  Apache Gora是一个开源的ORM框架,主要为大数据提供内存数据模型与数据的持久化。目前Gora支持对于列数据、key-value数据,文档数据与RDBMS数据的存储,还支持使用Apache Hadoop来对对大数据进行分析。



2. 为什么要使用Apache Gora

  虽然目前市面上有很多不错的关系数据库的ORM框架,但是基于数据模型的框架如JDO还是有一些不足,如对于列数据模型的存储与持久化。Gora正好弥补了这个问题,它能使用户很容易对大数据时行 内存建模与持久化,而且支持Hadoop来对大数据进行分析。


  说白了,Gora就是一个大数据的表示与持久化框架,它有如下特点
  •   数据持久化:它可以对列数据进行持久化,如HBase,Cassandra,Hypertable; key-value数据进行持久化,如Voldermort,Redis等,SQL数据库进行持久化,如MySQL,HSQLDB,也可以对文件进行HDFS存储 。
  •   数据访问:可以使用Java API对数据进行轻松的访问
  •   索引:可以持久化对象到Lucene或者Solr中去,可以使用Gora API来进行查询
  •   分析:可以使用Apache Pig,Hive,cascading来对数据进行分析
  •   MR的支持:原生支持Hadoop的MR框架,这个已经被用在Nutch 2.0上了


3. Gora的一个源代码结构

  Gora源代码以模块的形式来组织,其中gora-core是主要核心模块。所有其它模块都依赖这个核心模块,当然你可以扩展自己的模块,当前实现的模块如下

  •   gora-core : 核心模块
  •   gora-cassandra : apache cassandra模块
  •   gora-hbase : apache hbase模块
  •   gora-sql : sql数据库模块

4. 一个简单的例子


  下面这个例子是基于Gora中源代码中的gora-tutorial来说明的,在gora的源代码包中有这个目录。
  这个例子主要完成两上功能,一个是把目录中的测试数据放到HBase中,另一个是对HBase中的数据进行MR分析。


  下面先来看第一个功能:
  目前gora 0.2只支持hbase 0.90,hbase可以在hbase.apache.org上进行下载,下载先完成以后启动一个简单的服务,它把namenode+regionserver还有zookeeper都启动在一个jvm进程中,命令如下
[html] view plaincopy
  1. $ bin/start-hbase.sh  

  启动完成以后可以使用如下命令来测试
[html] view plaincopy
  1. bin/hbase shell  

  下来源代码中的测试数据进行解析,命令如下
[html] view plaincopy
  1. $ tar zxvf src/main/resources/access.log.tar.gz -C src/main/resources/  


  数据格式如下:
[html] view plaincopy
  1.   88.254.190.73 - - [10/Mar/2009:20:40:26 +0200] "GET / HTTP/1.1" 200 43 "http://www.buldinle.com/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; GTB5; .NET CLR 2.0.50727; InfoPath.2)"   
  2. 78.179.56.27 - - [11/Mar/2009:00:07:40 +0200] "GET /index.php?i=3&a=1__6x39kovbji8&k=3750105 HTTP/1.1" 200 43 "http://www.buldinle.com/index.php?i=3&a=1__6X39Kovbji8&k=3750105" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; OfficeLiveConnector.1.3; OfficeLivePatch.0.0)"   
  3. 78.163.99.14 - - [12/Mar/2009:18:18:25 +0200] "GET /index.php?a=3__x7l72c&k=4476881 HTTP/1.1" 200 43 "http://www.buldinle.com/index.php?a=3__x7l72c&k=4476881" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; InfoPath.1)"   


  下来是定义数据模型,Gora使用Apache Avro来定义数据的对象模型,avro可以方便的提供跟踪数对象的持久化状态与对象的持久化功能。定义数据模型还是比较简单的,它是以json格式来定义的,其中使用的PageView(src/main/avro/pageview.json)的定义格式如下:
[html] view plaincopy
  1.    {  
  2.   "type": "record",  
  3.   "name": "Pageview",  
  4.   "namespace": "org.apache.gora.tutorial.log.generated",  
  5.   "fields" : [  
  6.     {"name": "url", "type": "string"},  
  7.     {"name": "timestamp", "type": "long"},  
  8.     {"name": "ip", "type": "string"},  
  9.     {"name": "httpMethod", "type": "string"},  
  10.     {"name": "httpStatusCode", "type": "int"},  
  11.     {"name": "responseSize", "type": "int"},  
  12.     {"name": "referrer", "type": "string"},  
  13.     {"name": "userAgent", "type": "string"}  
  14.   ]  
  15. }  


   我们可以看到,其中的数据类型是record,name是生成的类的名称,而namespace是对应java中package的名字,而fields中定义的字段的名称与类型。


   下来是对定义好的数据模型进行编译,自动生成相应的代码,命令如下
[html] view plaincopy
  1. $ bin/gora compile  
  2.   
  3. $ Usage: SpecificCompiler <schema file> <output dir>  
  4.   
  5. $ bin/gora compile gora-tutorial/src/main/avro/pageview.json gora-tutorial/src/main/java/  


   编译以后生成文件 gora-tutorial/src/main/java/org/apache/gora/tutorial/log/generated/Pageview.java


   这里Gora的解析器扩展了Avro的SpecificCompiler方法,因为生成的对象模型在扩展自Gora自己的Persistent接口,而Persistent这个接口定义了对象的持久化,对象状态的跟踪等方法。下面是部分Pageview.java的代码
[java] view plaincopy
  1.  public class Pageview extends PersistentBase {  
  2.   
  3.   
  4. private Utf8 url;  
  5. private long timestamp;  
  6. private Utf8 ip;  
  7. private Utf8 httpMethod;  
  8. private int httpStatusCode;  
  9. private int responseSize;  
  10. private Utf8 referrer;  
  11. private Utf8 userAgent;  
  12.   
  13.   
  14. ...  
  15.   
  16.   
  17. public static final Schema _SCHEMA = Schema.parse("{\"type\":\"record\", ... ");  
  18. public static enum Field {  
  19.   URL(0,"url"),  
  20.   TIMESTAMP(1,"timestamp"),  
  21.   IP(2,"ip"),  
  22.   HTTP_METHOD(3,"httpMethod"),  
  23.   HTTP_STATUS_CODE(4,"httpStatusCode"),  
  24.   RESPONSE_SIZE(5,"responseSize"),  
  25.   REFERRER(6,"referrer"),  
  26.   USER_AGENT(7,"userAgent"),  
  27.   ;  
  28.   private int index;  
  29.   private String name;  
  30.   Field(int index, String name) {this.index=index;this.name=name;}  
  31.   public int getIndex() {return index;}  
  32.   public String getName() {return name;}  
  33.   public String toString() {return name;}  
  34. };  
  35. public static final String[] _ALL_FIELDS = {"url","timestamp","ip","httpMethod"  
  36.   ,"httpStatusCode","responseSize","referrer","userAgent",};  
  37.   
  38. ...  
  39. }  
  40.     


我们可以看到字段的声明,要注意的是在Avro中,使用Utf8这个类来实现string,我们还可以看到一个Avro Schema的声明,还有内嵌的枚举类型Field.

  
  Gora可以方便的定义不同类型的数据模型,如列数据模型(HBase,Cassandra),也有SQL数据模型,还有文件模型,如json,xml,并且还有key-value数据模型,而这些数据模型与数据存储之间的映射关系被定义在一个xml文件中,每一个数据存储抽象都有一个相对应的映射格式,这个映射文件声明了Avro schema中定义的类字段到数据存储抽象的一个映射关系,下面上面这个例子的一个HBase的映射文件, gora-hbase-mappings.xml

[html] view plaincopy
  1.       
  2. <gora-orm>  
  3.   <table name="Pageview"> <!-- optional descriptors for tables -->  
  4.     <family name="common"/> <!-- This can also have params like compression, bloom filters -->  
  5.     <family name="http"/>  
  6.     <family name="misc"/>  
  7.   </table>  
  8.   
  9.   
  10.   <class name="org.apache.gora.tutorial.log.generated.Pageview" keyClass="java.lang.Long" table="AccessLog">  
  11.     <field name="url" family="common" qualifier="url"/>  
  12.     <field name="timestamp" family="common" qualifier="timestamp"/>  
  13.     <field name="ip" family="common" qualifier="ip" />  
  14.     <field name="httpMethod" family="http" qualifier="httpMethod"/>  
  15.     <field name="httpStatusCode" family="http" qualifier="httpStatusCode"/>  
  16.     <field name="responseSize" family="http" qualifier="responseSize"/>  
  17.     <field name="referrer" family="misc" qualifier="referrer"/>  
  18.     <field name="userAgent" family="misc" qualifier="userAgent"/>  
  19.   </class>  
  20.     
  21.   ...  
  22.     
  23. </gora-orm>    
  24.         


 我们可以看到,这个映射文件以<gora-orm>标记为头节点,Hbase的Gora文件有两类节点,一个是table,别一个是class. 这里的table是可选的,它一般是用来来定义表的一些属性,如压缩,块缓冲等信息。而其中的class定义的Avro定义的类结构与数据存储之间的映射,其中的name定义的类名,keyClass定义的输入的<K,V>对中的K的类型,最后的那个table表示HBase所对应的表名,而field有三个属性,第一个是name,它表示类的成员名,并且它在HBase也表示column family的label,第二个是family,在HBase中表示column family,第三个是qualifier,它表示HBase中的column family。


 下面我们来运行其中的logmanager的例子
[html] view plaincopy
  1.       $ bin/gora logmanager  
  2.   
  3.   
  4. which lists the usage as:  
  5.   
  6.   
  7. LogManager -parse <input_log_file>  
  8.            -get <lineNum>  
  9.            -query <lineNum>  
  10.            -query <startLineNum> <endLineNum>  
  11.            -delete <lineNum>  
  12.            -deleteByQuery <startLineNum> <endLineNum>  

如下命令来运行解析程式

[html] view plaincopy
  1. $ bin/gora logmanager -parse gora-tutorial/src/main/resources/access.log  

你可以使用如下命令来查看HBase中的结果:


[html] view plaincopy
  1. hbase(main):004:0> scan 'AccessLog', {LIMIT=>1}  
  2. ROW                               COLUMN+CELL                                                                                      
  3.  \x00\x00\x00\x00\x00\x00\x00\x00 column=common:ip, timestamp=1342791952462value=88.240.129.183                                  
  4.  \x00\x00\x00\x00\x00\x00\x00\x00 column=common:timestamp, timestamp=1342791952462value=\x00\x00\x01\x1F\xF1\xAElP               
  5.  \x00\x00\x00\x00\x00\x00\x00\x00 column=common:url, timestamp=1342791952462value=/index.php?a=1__wwv40pdxdpo&k=218978           
  6.  \x00\x00\x00\x00\x00\x00\x00\x00 column=http:httpMethod, timestamp=1342791952462value=GET                                       
  7.  \x00\x00\x00\x00\x00\x00\x00\x00 column=http:httpStatusCode, timestamp=1342791952462value=\x00\x00\x00\xC8                      
  8.  \x00\x00\x00\x00\x00\x00\x00\x00 column=http:responseSize, timestamp=1342791952462value=\x00\x00\x00+                           
  9.  \x00\x00\x00\x00\x00\x00\x00\x00 column=misc:referrer, timestamp=1342791952462value=http://www.buldinle.com/index.php?a=1__WWV  
  10.                                   40pdxdpo&k=218978                                                                                
  11.  \x00\x00\x00\x00\x00\x00\x00\x00 column=misc:userAgent, timestamp=1342791952462value=Mozilla/4.0 (compatible; MSIE 6.0; Window  
  12.                                   s NT 5.1)                                                                                        
  13. 1 row(s) in 0.0180 seconds  


下来我们来分析一个这个程式,这个文件在gora-tutorial/src/main/java/org/apache/gora/tutorial/log/LogManager.java下面。


  •   初始化
     
[java] view plaincopy
  1. public LogManager() {  
  2.    try {  
  3.      init();  
  4.    } catch (IOException ex) {  
  5.      throw new RuntimeException(ex);  
  6.    }  
  7.  }  
  8.  private void init() throws IOException {  
  9.    dataStore = DataStoreFactory.getDataStore(Long.class, Pageview.class);  
  10.  }  


  这个方法主要是用于初始化DataStore,使用DataStoreFactory的静态方法,其中二个参数代表<K,V>,其中的DataStore是Gora中的一个重要的抽象,它用于操作对象的持久化,我们要吧用它来实现不同的module,如HBase,SQl等.


  下面的代码是用于解析日志与生成pageView对象。

[java] view plaincopy
  1.   private void parse(String input) throws IOException, ParseException {  
  2.   BufferedReader reader = new BufferedReader(new FileReader(input));  
  3.   long lineCount = 0;  
  4.   try {  
  5.     String line = reader.readLine();  
  6.     do {  
  7.       Pageview pageview = parseLine(line);  
  8.         
  9.       if(pageview != null) {  
  10.         //store the pageview   
  11.         storePageview(lineCount++, pageview);  
  12.       }  
  13.         
  14.       line = reader.readLine();  
  15.     } while(line != null);  
  16.       
  17.   } finally {  
  18.     reader.close();    
  19.   }  
  20. }  
  21.     
  22.   
  23. private Pageview parseLine(String line) throws ParseException {  
  24.   StringTokenizer matcher = new StringTokenizer(line);  
  25.   //parse the log line  
  26.   String ip = matcher.nextToken();  
  27.   ...  
  28.     
  29.   //construct and return pageview object  
  30.   Pageview pageview = new Pageview();  
  31.   pageview.setIp(new Utf8(ip));  
  32.   pageview.setTimestamp(timestamp);  
  33.   ...  
  34.     
  35.   return pageview;  
  36. }  


  最后是存储对象到后台存储模型中,用完以后别忘了关闭存储

[html] view plaincopy
  1. /** Stores the pageview object with the given key */  
  2. ivate void storePageview(long key, Pageview pageview) throws IOException {  
  3. dataStore.put(key, pageview);  
  4.   
  5.   
  6.   
  7. private void close() throws IOException {  
  8. //It is very important to close the datastore properly, otherwise  
  9. //some data loss might occur.  
  10. if(dataStore != null)  
  11.   dataStore.close();  


  从数据库中取数据

[java] view plaincopy
  1.   /** Fetches a single pageview object and prints it*/  
  2. private void get(long key) throws IOException {  
  3.   Pageview pageview = dataStore.get(key);  
  4.   printPageview(pageview);  
  5. }  


  查询对象

[java] view plaincopy
  1.   /** Queries and prints pageview object that have keys between startKey and endKey*/  
  2. private void query(long startKey, long endKey) throws IOException {  
  3.   Query<Long, Pageview> query = dataStore.newQuery();  
  4.   //set the properties of query  
  5.   query.setStartKey(startKey);  
  6.   query.setEndKey(endKey);  
  7.     
  8.   Result<Long, Pageview> result = query.execute();  
  9.     
  10.   printResult(result);  
  11. }  
  12.     


删除对象

[java] view plaincopy
  1.  /**Deletes the pageview with the given line number */  
  2. private void delete(long lineNum) throws Exception {  
  3.   dataStore.delete(lineNum);  
  4.   dataStore.flush(); //write changes may need to be flushed before  
  5.                      //they are committed   
  6. }  
  7.   
  8. /** This method illustrates delete by query call */  
  9. private void deleteByQuery(long startKey, long endKey) throws IOException {  
  10.   //Constructs a query from the dataStore. The matching rows to this query will be deleted  
  11.   QueryLong, Pageview> query = dataStore.newQuery();  
  12.   //set the properties of query  
  13.   query.setStartKey(startKey);  
  14.   query.setEndKey(endKey);  
  15.     
  16.   dataStore.deleteByQuery(query);  
  17. }     

5. 参考

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

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


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

0 0
原创粉丝点击