Nutch2.0 之 Apache Gora 介绍

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进程中,命令如下
  $ bin/start-hbase.sh

  启动完成以后可以使用如下命令来测试
  bin/hbase shell

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


  数据格式如下:
  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)" 
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)" 
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)的定义格式如下:
   {
  "type": "record",
  "name": "Pageview",
  "namespace": "org.apache.gora.tutorial.log.generated",
  "fields" : [
    {"name": "url", "type": "string"},
    {"name": "timestamp", "type": "long"},
    {"name": "ip", "type": "string"},
    {"name": "httpMethod", "type": "string"},
    {"name": "httpStatusCode", "type": "int"},
    {"name": "responseSize", "type": "int"},
    {"name": "referrer", "type": "string"},
    {"name": "userAgent", "type": "string"}
  ]
}


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


   下来是对定义好的数据模型进行编译,自动生成相应的代码,命令如下
   $ bin/gora compile

   $ Usage: SpecificCompiler <schema file> <output dir>

   $ 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的代码

   public class Pageview extends PersistentBase {


  private Utf8 url;
  private long timestamp;
  private Utf8 ip;
  private Utf8 httpMethod;
  private int httpStatusCode;
  private int responseSize;
  private Utf8 referrer;
  private Utf8 userAgent;


  ...


  public static final Schema _SCHEMA = Schema.parse("{\"type\":\"record\", ... ");
  public static enum Field {
    URL(0,"url"),
    TIMESTAMP(1,"timestamp"),
    IP(2,"ip"),
    HTTP_METHOD(3,"httpMethod"),
    HTTP_STATUS_CODE(4,"httpStatusCode"),
    RESPONSE_SIZE(5,"responseSize"),
    REFERRER(6,"referrer"),
    USER_AGENT(7,"userAgent"),
    ;
    private int index;
    private String name;
    Field(int index, String name) {this.index=index;this.name=name;}
    public int getIndex() {return index;}
    public String getName() {return name;}
    public String toString() {return name;}
  };
  public static final String[] _ALL_FIELDS = {"url","timestamp","ip","httpMethod"
    ,"httpStatusCode","responseSize","referrer","userAgent",};
  
  ...
  }
    


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

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

    
<gora-orm>
  <table name="Pageview"> <!-- optional descriptors for tables -->
    <family name="common"/> <!-- This can also have params like compression, bloom filters -->
    <family name="http"/>
    <family name="misc"/>
  </table>


  <class name="org.apache.gora.tutorial.log.generated.Pageview" keyClass="java.lang.Long" table="AccessLog">
    <field name="url" family="common" qualifier="url"/>
    <field name="timestamp" family="common" qualifier="timestamp"/>
    <field name="ip" family="common" qualifier="ip" />
    <field name="httpMethod" family="http" qualifier="httpMethod"/>
    <field name="httpStatusCode" family="http" qualifier="httpStatusCode"/>
    <field name="responseSize" family="http" qualifier="responseSize"/>
    <field name="referrer" family="misc" qualifier="referrer"/>
    <field name="userAgent" family="misc" qualifier="userAgent"/>
  </class>
  
  ...
  
</gora-orm>  
      


 我们可以看到,这个映射文件以<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的例子

	  $ bin/gora logmanager


which lists the usage as:


LogManager -parse <input_log_file>
           -get <lineNum>
           -query <lineNum>
           -query <startLineNum> <endLineNum>
           -delete <lineNum>
           -deleteByQuery <startLineNum> <endLineNum>

如下命令来运行解析程式

$ bin/gora logmanager -parse gora-tutorial/src/main/resources/access.log

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


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


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


  •   初始化
     
 public LogManager() {
    try {
      init();
    } catch (IOException ex) {
      throw new RuntimeException(ex);
    }
  }
  private void init() throws IOException {
    dataStore = DataStoreFactory.getDataStore(Long.class, Pageview.class);
  }


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


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

    private void parse(String input) throws IOException, ParseException {
    BufferedReader reader = new BufferedReader(new FileReader(input));
    long lineCount = 0;
    try {
      String line = reader.readLine();
      do {
        Pageview pageview = parseLine(line);
        
        if(pageview != null) {
          //store the pageview 
          storePageview(lineCount++, pageview);
        }
        
        line = reader.readLine();
      } while(line != null);
      
    } finally {
      reader.close();  
    }
  }
    

  private Pageview parseLine(String line) throws ParseException {
    StringTokenizer matcher = new StringTokenizer(line);
    //parse the log line
    String ip = matcher.nextToken();
    ...
    
    //construct and return pageview object
    Pageview pageview = new Pageview();
    pageview.setIp(new Utf8(ip));
    pageview.setTimestamp(timestamp);
    ...
    
    return pageview;
  }


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

    /** Stores the pageview object with the given key */
  private void storePageview(long key, Pageview pageview) throws IOException {
    dataStore.put(key, pageview);
  }


    private void close() throws IOException {
    //It is very important to close the datastore properly, otherwise
    //some data loss might occur.
    if(dataStore != null)
      dataStore.close();
  }


  从数据库中取数据

    /** Fetches a single pageview object and prints it*/
  private void get(long key) throws IOException {
    Pageview pageview = dataStore.get(key);
    printPageview(pageview);
  }


  查询对象

    /** Queries and prints pageview object that have keys between startKey and endKey*/
  private void query(long startKey, long endKey) throws IOException {
    Query<Long, Pageview> query = dataStore.newQuery();
    //set the properties of query
    query.setStartKey(startKey);
    query.setEndKey(endKey);
    
    Result<Long, Pageview> result = query.execute();
    
    printResult(result);
  }
    


删除对象

	  /**Deletes the pageview with the given line number */
  private void delete(long lineNum) throws Exception {
    dataStore.delete(lineNum);
    dataStore.flush(); //write changes may need to be flushed before
                       //they are committed 
  }
  
  /** This method illustrates delete by query call */
  private void deleteByQuery(long startKey, long endKey) throws IOException {
    //Constructs a query from the dataStore. The matching rows to this query will be deleted
    QueryLong, Pageview> query = dataStore.newQuery();
    //set the properties of query
    query.setStartKey(startKey);
    query.setEndKey(endKey);
    
    dataStore.deleteByQuery(query);
  }   

5. 参考

http://gora.apache.org/docs/current/quickstart.html
http://gora.apache.org/docs/current/tutorial.html
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值