一、协处理器介绍
定义:HBase可以让用户的部分逻辑在数据存放端及hbase服务端进行计算的机制(框架)。协处理器允许用户在hbase服务端上运行自己的代码。
分类:系统协处理器、表协处理器
observer,相当于关系型数据库里面的触发器
endpoint,类似于存储过程
二、OBserver
观察者的设计意图是允许用户通过插入代码来重载协处理器框架的upcall方法,而具体的事件触发的callback方法由HBase的核心代码来执行。可以分为RegionObserver、RegionServerObserver、MasterObserver、WalObserver
RegionObserver 提供客户端的数据操纵事件钩子: Get、 Put、 Delete、Scan等
RegionServerObserver 专门处理RegionServer上的一些事件
MasterObserver 提供DDL-类型的操作钩子。如创建、删除、修改数据表等
WalObserver 提供WAL相关操作
这些接口可以同时使用在同一个地方,按照不同优先级顺序执行.用户可以任意基于协处理器实现复杂的HBase功能层。HBase有很多种事件可以触发观察者方法,这些事件与方法从HBase0.92版本起,都会集成在HBase API中。不过这些API可能会由于各种原因有所
改动,不同版本的接口改动比较大。RegionObserver工作原理如下图所示。
三、Endpoint
终端是动态RPC插件的接口,它的实现代码被安装在服务器端,从而能够通过HBase RPC唤醒。客户端类库提供了非常方便的方法来调用这些动态接口,它们可以在任意时候调用一个终端,它们的实现代码会被目标region远程执行,结果会返回到终端。用户可以结合使
用这些强大的插件接口,为HBase添加全新的特性。
endpoint服务端编写
1.创建endpoint.proto文件,生成java文件
- option java_package = "edu.endpoint";
- option java_outer_classname = "Sum";
- option java_generic_services = true;
- option java_generate_equals_and_hash = true;
- option optimize_for = SPEED;
- message SumRequest {
- required string family = 1;
- required string column = 2;
- }
- message SumResponse {
- required int64 sum = 1 [default = 0];
- }
- service SumService {
- rpc getSum(SumRequest)
- returns (SumResponse);
- }
2.将.proto文件生成Java代码。
protoc endpoint.proto –java_out=./
将生成的.java文件拷贝到eclipse对应的java项目源代码包文件下。添加hbase lib下所有依赖库文件。
3.编写服务端SumEndpoint.java类
- package edu.endpoint;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
- import org.apache.hadoop.hbase.Coprocessor;
- import org.apache.hadoop.hbase.CoprocessorEnvironment;
- import org.apache.hadoop.hbase.client.Scan;
- import org.apache.hadoop.hbase.coprocessor.CoprocessorException;
- import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
- import org.apache.hadoop.hbase.regionserver.InternalScanner;
- import org.apache.hadoop.hbase.util.Bytes;
- import com.google.protobuf.RpcCallback;
- import com.google.protobuf.RpcController;
- import com.google.protobuf.Service;
- import edu.endpoint.Sum.SumRequest;
- import edu.endpoint.Sum.SumResponse;
- import edu.endpoint.Sum.SumService;
- public class SumEndPoint extends SumService implements Coprocessor,CoprocessorService{
- private RegionCoprocessorEnvironment env;
- public void getSum(RpcController controller,SumRequest request,RpcCallback<SumResponse> done) throws IOException{
- Scan scan = new Scan();
- scan.addFamily(Bytes.toBytes(request.getFamily()));
- scan.addColumn(Bytes.toBytes(request.getFamily()), Bytes.toBytes(request.getColumn()));
- SumResponse response = null;
- InternalScanner scanner = null;
- try{
- scanner = env.getRegion().getScanner(scan);
- List<Cell> results = new ArrayList<Cell>();
- boolean hasMore = false;
- Long sum = 0;
- do {
- hasMore = scanner.next(results);
- for(Cell cell:results){
- sum += Long.parseLong(new String(CellUtil.cloneValue(cell)));
- }
- results.clear();
- } while (hasMore);
- response = SumResponse.newBuilder().setSum(sum).build();
- }catch (IOException e) {
- ResponseConverter.setControllerException(controller,e);
- }finally {
- if (scanner!=null) {
- try {
- scanner.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- done.run(response);
- }
- public Service getService(){
- return this;
- }
- @Override
- public void start(CoprocessorEnvironment env) throws IOException {
- if (env instanceof RegionCoprocessorEnvironment) {
- this.env =(RegionCoprocessorEnvironment) env;
- }else {
- throw new CoprocessorException("no load region");
- }
- }
- @Override
- public void stop(CoprocessorEnvironment arg0) throws IOException {
- }
- }