HBase协处理器

  1. 协处理器接口:
    RegionObserver:用于处理数据修改事件,与表的region相关联。
    MasterObserver:用作管理或者是DDL类型操作,属于集群级别事件。
    WALObserver:提供控制WAL的钩子函数。
  2. 协处理器的加载③④⑤⑥
    ①.从配置文件加载:
<property>
    <name>hbase.coprocessor.region.classes</name>
    <value>com.ronnie.coprocess.RegionCoprocess,com.ronnie.hbase..</value>
</property>
<property>
    <name>hbase.coprocessor.master.classes</name>
    <value>com.ronnie.hbase.MasterCoprocessor</value>
</property>
<property>
    <name>hbase.coprocessor.wal.classes</name>
    <value>com.ronnie.hbase.WALCoprocessor</value>
</property>

②指定特定的表:

public static void main(String[] args) throws IOException {
    /*
     * 该方法只针对特定的表,对特定表对应的region才回去加载协处理器类。其他的都不会加载。
     */
    Configuration conf = HBaseConfiguration.create();
    Connection connection = ConnectionFactory.createConnection(conf);
    FileSystem fileSystem = FileSystem.get(conf);
    //会到该路径去找到对应的协处理类。
    Path path = new Path(fileSystem.getUri() + Path.SEPARATOR + "test.jar");
    HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("testTable"));
    desc.addFamily(new HColumnDescriptor(Bytes.toBytes("faimly-1")));
    /*
     * $1表示加载协处理器的顺序。(当是user的时候)
     */
    desc.setValue("COPROCESSOR$1", path.toString() + 
            "|" + RegionObserver.class.getCanonicalName() + 
            "|" + Coprocessor.PRIORITY_USER);
    Admin admin = connection.getAdmin();
    admin.createTable(desc);
}

3.Observer

/**
 *   只作用在region服务器上
 */
public class RegionObserver extends BaseRegionObserver {
    private static final byte[] FIX_ROW = "daxian".getBytes();
    @Override
    public void preGetOp(ObserverContext<RegionCoprocessorEnvironment> e,
            Get get, List<Cell> results) throws IOException {
        if(Bytes.equals(get.getRow(), FIX_ROW)){
            Cell ce = CellUtil.createCell(get.getRow(), FIX_ROW, FIX_ROW, System.currentTimeMillis(), (byte)3, Bytes.toBytes(""));
            KeyValue kv = KeyValueUtil.copyToNewKeyValue(ce);
            kv.getValueArray();


            Cell cell = new KeyValue(get.getRow(),//row 
                                    FIX_ROW,//family 
                                    FIX_ROW, //column
                                    Bytes.toBytes(System.currentTimeMillis()));//value
            results.add(cell);
            e.bypass();//则会将以前的数据忽略掉,而是使用用户自定义的数据
            e.complete();//告诉框架后续的操作可以被跳过,剩下没有被调用的协处理器也将被跳过,即表示该协处理器为最后一个处理器。
        }
    }

}
/**
 *  表示在创建表之后创建对应的目录。
 */
public class MasterObserver extends BaseMasterObserver{
    @Override
    public void postCreateTable(
            ObserverContext<MasterCoprocessorEnvironment> ctx,
            HTableDescriptor desc, HRegionInfo[] regions) throws IOException {
        //得到创建的表的名字:两种方式均可得到创建表的名字
        String tableName = regions[0].getTable().getNameAsString();
        String tn = desc.getNameAsString();
        //获得master对应的文件系统,getMasterFileSystem:用于用户创建表或日志文件目录等操作
        FileSystem fileSystem = ctx.getEnvironment().getMasterServices().getMasterFileSystem().getFileSystem();
        Path path1 = new Path(tableName + "_regions");
        Path path2 = new Path(tn + "_desc");

        fileSystem.mkdirs(path1);
        fileSystem.mkdirs(path2);

    }
}

4.endpoint、

在0.98 的版本之后,采用的google 的protobuf处理RPC调用。

message SearchRequest{
    required string query = 1;//required表示必须出现,string类型的默认值为空字符串
    option int32 page_number = 2;//option表示可以出现一次或是0次。int默认值为0
    option int32 result_per_page = 3;
    enum Corpus{
        UNIVERSAL = 0;
        WEB = 1;
        IMAGES = 2;
        LOCAL = 3;
        NEWS = 4;
        PRODUCTS = 5;
        VIDEO = 6;
    }
    option Corpus corpus = 4 [default = UNIVERSAL];//对于enum,默认值为列表的第一个元素
    repeated string name = 5;//repeat表示可以重复出现多次。

}
message SearchResponse{
    repeated Result result = 1;//类型也可以是自定义的类型。
}

message Result{
    required string url = 1;
    optional string title = 2;
    repeated string snippet = 3;
}

----------------------------------------------------------
message SearchResponse{
    message Result{
        required string url = 1;
        optional string title = 2;
        repeated string snippets = 3;

    }
    repeated Result result = 1;

}
message SomeOtherMessage{
    optional SearchResponse.Result result = 1;//也支持这样进行调用。
}
-----------------------------------
Group:
message SearchResponse{
    repeated group Result = 1 {
        required string url = 2;
        optional string title = 3;
        repeated string snippets = 4;
    }
}

----------------------------------
有些option必须写在message外面:
option java_package = "";//对应java的包名。
option java_outer_classname = "";//对应java的类名
option optimize_for = "";//
/**
 * optimize_for可以取值为:SPEED\CODE_SIZE\LITE_RUNTIME
 *  SPEED :默认
 *
 */
option cc_generic_services|java_generic_services|python_generic_services


============================endpoint========================================
protoc -I=. --java_out=../src/main/java ./sum.proto #-I后面跟的是.proto所在的目录,--java_out后面的路径一般设为
            protobuf中java/src/main/java
然后对项目进行编译 : mvn clean compile
打包为jar包:mvn install 得到对应的protobuf-java-versionid.jar
最后将jar包放到hbase的lib目录下,如果你的客户端不是region服务器,可将该包拷贝下来进行使用。


写客户端的endpoint代码:需要继承由protoc 生成的Service代码,然后进行编写。
----------------------------------------------------------------------------
public class RowCountProtocol extends Sum.SumService implements Coprocessor,CoprocessorService {

    private RegionCoprocessorEnvironment environment;
    /**
     * 从SumService中继承而来。
     */
    @Override
    public void getSum(RpcController controller, SumRequest request,
            RpcCallback<SumResponse> done) {
        Scan scan = new Scan();
        //定义过的family和column
        scan.addFamily(Bytes.toBytes(request.getFamily()));
        scan.addColumn(Bytes.toBytes(request.getFamily()), Bytes.toBytes(request.getColumn()));

        SumResponse response = null;

        try(InternalScanner scanner = environment.getRegion().getScanner(scan)) {
            List<Cell> results = new ArrayList<Cell>();
            boolean hasMore = false;
            long sum = 0l;

            do{
                hasMore = scanner.next(results);
                for(Cell cell : results){
                    sum += Bytes.toLong(CellUtil.cloneValue(cell));
                }
                results.clear();
            }while(hasMore);
            response = SumResponse.newBuilder().setSum((int) sum).build();
        } catch (IOException ioe) {
            ResponseConverter.setControllerException(controller, ioe);
        }
        done.run(response);

    }

    @Override
    public Service getService() {
        return this;
    }

    @Override
    public void start(CoprocessorEnvironment env) throws IOException {
        if(env instanceof RegionCoprocessorEnvironment){
            environment = (RegionCoprocessorEnvironment) env;
        }else{
            throw new CoprocessorException("must loaded a table region");
        }
    }

    @Override
    public void stop(CoprocessorEnvironment env) throws IOException {

    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值