hbase for hadoop2.X 使用 protocolbuffer 自定義filter

一.所需技能
1.搭建環境請參考http://blog.csdn.net/hadoop_83425744/article/details/49254741裏面環境搭建
2.必須掌握protocol buffer
3.瞭解hbase的流程
二.環境搭建
1.推薦環境搭建使用linux,通過hadoop在windows的二次開發的教訓決定直接使用linux環境開發,win環境錯誤可以留言幫其他人蔘考
2.通過之前的hadoop的搭建文章我們照搬過來,下載hbase源碼並打開,下載地址http://archive.apache.org/dist/hbase/ 請務必下載 hbase-version-src.tar.gz 的文件
3.下載好了之後導入全部的文件,修改pom文件,使用pom.xml.hadoop2 的文件作爲項目的pom文件,參考hadoop文章,至此我們就搭建好了一個hbase開發環境,如果有錯誤且自己有強迫症,請在錯誤的項目下面導入hbase程序的lib下面所有的包
三.大概思路
1.開發自定義的filter我們需要首先開發他的通訊協議,因爲hbase是通過protocol buffer序列化,我們首先進行filter protocol的開發
2.協議導入之後我們可以直接開發filter,在開發中切記加入tobytes和parsen(稍後會講解)
四.開始開發filter
本案例演示如何開發一個過濾key的filter
1.開發filter需要了解的2個文件結構
這裏寫圖片描述
a.hbase-client是我們需要寫filter的項目
b.hbase-protocol是我們開發所有的通訊協議的項目,我們的protocol就在這裏加工

 1.開發protocol buffer
     a.找到hbase-protocol項目,
       1.org.apache.hadoop.hbase.protobuf.generated是protocol文件生成代碼的地方
       2.src.main.protobuf文件夾下面是存放所有proto文件的地方
     b.接下來找到我們需要添加的Filter.proto文件並打開
         ![這裏寫圖片描述](https://img-blog.csdn.net/20151120151738499)
      1. 根據上面的內容我們模仿添加一個myfilter的對像,無屬性,(可以填寫屬性,但是如果有屬性必須在序列化的時候添加參數,否則程序卡死也不會出現報錯,深坑) 
      2. 因爲嘗試使用mvn命令generated無法自動生成java,所以使用命令行直接生成並覆蓋原來的FilterProtos.hava文件 

           a.跳轉到src.main.protobuf,運行命令 protoc --java_out=./ Filter.proto  一定要跳到這個目錄下面,否則容易粗大事 

           b.生成好了我們點進去...發現現在目錄下面又生成了org.apache.hadoop.hbase.protobuf.generated文件目錄..我們進去找到我們生成的代碼,然後覆蓋之前在src.main.org.apache.hadoop.hbase.protobuf.generated 

           c.成功完成了protocol的開發,我們打包. 在項目下面輸入mvn package 後在target找到生成的jar文件, 

           d.把生成的jar文件放到我們的集羣的{{hbasehome}}/lib/下面,替換原來的 

            e.如果在windows 開發使用mvn管理的也需要替換maven倉庫中的hbase-protocol,替換好了就OK了

            f.最後一步在client中關聯現在的包此時,我們的client也可以使用我們的protocol buffer啦
            ![這裏寫圖片描述](https://img-blog.csdn.net/20151120153825438)

2.開發filter
a.在org.apache.hadoop.hbase.filter下面創建一個類 myFilter(爲什麼一定要在這裏開發,因爲basefilter 類裏面的序列化是個私有方法,在其他地方無法調用,所以也就無法完成單獨jar開發的任務)

package org.apache.hadoop.hbase.filter;

import java.io.IOException;
import java.util.ArrayList;

import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.KeyValueUtil;
import org.apache.hadoop.hbase.exceptions.DeserializationException;
import org.apache.hadoop.hbase.filter.Filter;
import org.apache.hadoop.hbase.filter.FilterBase;
import org.apache.hadoop.hbase.protobuf.generated.FilterProtos;
import org.junit.Test;

import com.google.protobuf.InvalidProtocolBufferException;

@InterfaceAudience.Public
@InterfaceStability.Stable
public class MyFilter extends FilterBase {
/**
* true的時候就表示該行被過濾
*/
private boolean filterRow = false;

public MyFilter() {
}
/**
 * 如果scan 已經指定列族裏面的列標示符,cell就是標示符的這一列,如果沒有指定列標示符,他會循環調用每一列,
 所以我這裏可以判斷只有screen這一列的時候才進行判斷,遇到其他列就直接跳過
 */
@Override
public ReturnCode filterKeyValue(Cell cell) throws IOException {
    if (new String(CellUtil.cloneQualifier(cell)).equals("screen")) {
        if (new String(CellUtil.cloneValue(cell)).equals("1440x900")) {
            return ReturnCode.INCLUDE;
        } else {
            this.filterRow = true;
            return ReturnCode.SKIP;
        }
    } else {
        return ReturnCode.NEXT_COL;
    }
}
/**
 * 返回該行是否被過濾
 */
@Override
public boolean filterRow() throws IOException {
    return this.filterRow;
}
/**
 * 每行完成之後重置
 */
@Override
public void reset() throws IOException {
    this.filterRow = false;
}
/**
 * 通過參數創建一個filter 參照其他過濾器使用
 * @param filterArguments
 * @return
 */
public static Filter createFilterFromArguments(
        ArrayList<byte[]> filterArguments) {
    return new MyFilter();
}
/**
 * 使用PB序列化對象
 */
public byte[] toByteArray() {
    FilterProtos.MyFilter.Builder builder = FilterProtos.MyFilter
            .newBuilder();
    byte[] byteArray = builder.build().toByteArray();
    return byteArray;
}
/**
 * 
 * @param pbBytes
 * @return 這裏本來是解析參數的,因爲我這裏沒有參數 所以不用填寫 如需要參數可以參照其他過濾器
 * @throws DeserializationException
 */
public static MyFilter parseFrom(final byte[] pbBytes)
        throws DeserializationException {
    try {
        FilterProtos.MyFilter.parseFrom(pbBytes);
    } catch (InvalidProtocolBufferException e) {
        throw new DeserializationException(e);
    }
    return new MyFilter();
}
/**
 * 標記是否進行序列化 我們這裏選擇是 參照keyvaluefilter
 */
boolean areSerializedFieldsEqual(Filter o) {
    if (o == this)
        return true;
    if (!(o instanceof MyFilter))
        return false;
    return true;
}
// @Test
// public void testPB(){
// FilterProtos.MyFilter.Builder builder =
// FilterProtos.MyFilter.newBuilder();
// byte[] byteArray = builder.build().toByteArray();
// }

}

b.寫完之後可以參照protocol中的c d e步驟
3.把兩個包都分別放入了我們生成集羣的lib下面和我們開發所需的maven倉庫之後,便可以直接調用啦, 經過改造我們不需指定列標示符就能得到1440*900的分辨率的信息
@Test
public void testMyFilter(){
// scan.addColumn(INFO, SCREEN);
Filter myFilter = new org.apache.hadoop.hbase.filter.MyFilter();
scan.setFilter(myFilter);
getres();
}
五,如需開發其他類型的filter,請參照其他filter開發,returnCode類裏面的參數在開發前務必看一遍,瞭解參數類型

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章