HBase Coprocessor 之 endpiont(hbase 0.96.0)

好文章。收藏下


本文是基于hbase 0.96.0 测试的,理论上支持hbase 0.94 以上版本!!

HBase有两种协处理器(Coprocessor)

1、RegionObserver :类似于关系型数据库的触发器

2、Endpoint:类似于关系型数据库的存储过程,本文将介绍此种Coprocessor.

Endpoint 允许您定义自己的动态RPC协议,用于客户端与region servers通讯。Coprocessor 与region server在相同的进程空间中,因此您可以在region端定义自己的方法(endpoint),将计算放到region端,减少网络开销,常用于提升hbase的功能,如:count,sum等。


本文以count为例,实现一个自己的endpoint:

一、定义一个protocol buffer Service。

1、安装protobuf

下载protoc-2.5.0-win32.zip(根据自己的操作系统选择),解压;

将protoc-2.5.0-win32中的protoc.exe拷贝到c:\windows\system32中。

将proto.exe文件拷贝到解压后的XXX\protobuf-2.5.0\src目录中.

参考链接:http://shuofenglxy.iteye.com/blog/1512980

2.定义.proto文件,用于定义类的一些基本信息

CXKTest.proto的代码如下:

[html]  view plain copy
  1. <span style="font-family:SimSun;font-size:14px;">option java_package = "com.cxk.coprocessor.test.generated";  
  2. option java_outer_classname = "CXKTestProtos";  
  3. option java_generic_services = true;  
  4. option java_generate_equals_and_hash = true;  
  5. option optimize_for = SPEED;  
  6. message CountRequest {  
  7. }  
  8. message CountResponse {  
  9.   required int64 count = 1 [default = 0];  
  10. }  
  11. service RowCountService {  
  12.   rpc getRowCount(CountRequest)  
  13.     returns (CountResponse);  
  14. }span>  

参考链接:https://developers.google.com/protocol-buffers/docs/proto#services

3.用proto.exe 生成java代码
执行命令:proto.exe--java_out=. CXKTest.proto

在 com.cxk.coprocessor.test.generated 下会生成类:CXKTestProtos

二、定义自己的Endpoint类(实现一下自己的方法)

RowCountEndpoint.java 的代码片段如下:

[html]  view plain copy
  1. <span style="font-family:SimSun;font-size:14px;">package com.cxk.coprocessor.test;  
  2. import java.io.IOException;  
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5. import org.apache.hadoop.hbase.Cell;  
  6. import org.apache.hadoop.hbase.CellUtil;  
  7. import org.apache.hadoop.hbase.Coprocessor;  
  8. import org.apache.hadoop.hbase.CoprocessorEnvironment;  
  9. import org.apache.hadoop.hbase.client.Scan;  
  10. import org.apache.hadoop.hbase.coprocessor.CoprocessorException;  
  11. import org.apache.hadoop.hbase.coprocessor.CoprocessorService;  
  12. import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;  
  13. import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;  
  14. import org.apache.hadoop.hbase.protobuf.ResponseConverter;  
  15. import org.apache.hadoop.hbase.regionserver.InternalScanner;  
  16. import org.apache.hadoop.hbase.util.Bytes;  
  17. import com.google.protobuf.RpcCallback;  
  18. import com.google.protobuf.RpcController;  
  19. import com.google.protobuf.Service;  
  20.   
  21. public class RowCountEndpoint extends CXKTestProtos.RowCountService  
  22.     implements Coprocessor, CoprocessorService {  
  23.   private RegionCoprocessorEnvironment env;  
  24.   
  25.   public RowCountEndpoint() {  
  26.   }  
  27.   
  28.   @Override  
  29.   public Service getService() {  
  30.     return this;  
  31.   }  
  32.   
  33.   /**  
  34.    * 统计hbase表总行数  
  35.    */  
  36.   @Override  
  37.   public void getRowCount(RpcController controller, CXKTestProtos.CountRequest request,  
  38.                           RpcCallback<CXKTestProtos.CountResponse> done) {  
  39.     Scan scan = new Scan();  
  40.     scan.setFilter(new FirstKeyOnlyFilter());  
  41.     CXKTestProtos.CountResponse response = null;  
  42.     InternalScanner scanner = null;  
  43.     try {  
  44.       scanner = env.getRegion().getScanner(scan);  
  45.       List<Cell> results = new ArrayList<Cell>();  
  46.       boolean hasMore = false;  
  47.       byte[] lastRow = null;  
  48.       long count = 0;  
  49.       do {  
  50.         hasMore = scanner.next(results);  
  51.         for (Cell kv : results) {  
  52.           byte[] currentRow = CellUtil.cloneRow(kv);  
  53.           if (lastRow == null || !Bytes.equals(lastRow, currentRow)) {  
  54.             lastRow = currentRow;  
  55.             count++;  
  56.           }  
  57.         }  
  58.         results.clear();  
  59.       } while (hasMore);  
  60.   
  61.       response = CXKTestProtos.CountResponse.newBuilder()  
  62.           .setCount(count).build();  
  63.     } catch (IOException ioe) {  
  64.       ResponseConverter.setControllerException(controller, ioe);  
  65.     } finally {  
  66.       if (scanner != null) {  
  67.         try {  
  68.           scanner.close();  
  69.         } catch (IOException ignored) {}  
  70.       }  
  71.     }  
  72.     done.run(response);  
  73.   }  
  74.   
  75.   @Override  
  76.   public void start(CoprocessorEnvironment env) throws IOException {  
  77.     if (env instanceof RegionCoprocessorEnvironment) {  
  78.       this.env = (RegionCoprocessorEnvironment)env;  
  79.     } else {  
  80.       throw new CoprocessorException("Must be loaded on a table region!");  
  81.     }  
  82.   }  
  83.   
  84.   @Override  
  85.   public void stop(CoprocessorEnvironment env) throws IOException {  
  86.     // nothing to do  
  87.   }  
  88. }  
  89. span>  

三、实现自己的客户端方法:

TestEndPoint.java 代码如下:

[html]  view plain copy
  1. <span style="font-family:SimSun;font-size:14px;">package com.test;  
  2.   
  3.   
  4. import java.io.IOException;  
  5. import java.util.Map;  
  6.   
  7. import org.apache.hadoop.conf.Configuration;  
  8. import org.apache.hadoop.hbase.HBaseConfiguration;  
  9. import org.apache.hadoop.hbase.client.HTable;  
  10. import org.apache.hadoop.hbase.client.coprocessor.Batch;  
  11. import org.apache.hadoop.hbase.ipc.BlockingRpcCallback;  
  12. import org.apache.hadoop.hbase.ipc.ServerRpcController;  
  13.   
  14. import com.cxk.coprocessor.test.CXKTestProtos;  
  15. import com.cxk.coprocessor.test.CXKTestProtos.RowCountService;  
  16. import com.google.protobuf.ServiceException;  
  17.   
  18. public class TestEndPoint {  
  19. /**  
  20.  *   
  21.  * @param args[0] ip ,args[1] zk_ip,args[2] table_name  
  22.  * @throws ServiceException  
  23.  * @throws Throwable  
  24.  */  
  25.     public static void main(String[] args) throws ServiceException, Throwable {  
  26.         // TODO Auto-generated method stub  
  27.          System.out.println("begin.....");  
  28.          long begin_time=System.currentTimeMillis();  
  29.         Configuration config=HBaseConfiguration.create();  
  30. //      String master_ip="192.168.150.128";  
  31.         String master_ip=args[0];  
  32.         String zk_ip=args[1];  
  33.         String table_name=args[2];  
  34.         config.set("hbase.zookeeper.property.clientPort", "2181");   
  35.         config.set("hbase.zookeeper.quorum", zk_ip);   
  36.         config.set("hbase.master", master_ip+":600000");  
  37.         final CXKTestProtos.CountRequest request = CXKTestProtos.CountRequest.getDefaultInstance();  
  38.         HTable table=new HTable(config,table_name);  
  39.           
  40.         Map<byte[],Long> results = table.coprocessorService(RowCountService.class,  
  41.                 null, null,  
  42.                 new Batch.Call<CXKTestProtos.RowCountService,Long>() {  
  43.                   public Long call(CXKTestProtos.RowCountService counter) throws IOException {  
  44.                     ServerRpcController controller = new ServerRpcController();  
  45.                     BlockingRpcCallback<CXKTestProtos.CountResponse> rpcCallback =  
  46.                         new BlockingRpcCallback<CXKTestProtos.CountResponse>();  
  47.                     counter.getRowCount(controller, request, rpcCallback);  
  48.                     CXKTestProtos.CountResponse response = rpcCallback.get();  
  49.                     if (controller.failedOnException()) {  
  50.                       throw controller.getFailedOn();  
  51.                     }  
  52.                     return (response != null && response.hasCount()) ? response.getCount() : 0;  
  53.                   }  
  54.                 });  
  55.         table.close();  
  56.   
  57.          if(results.size()>0){  
  58.          System.out.println(results.values());  
  59.          }else{  
  60.              System.out.println("没有任何返回结果");  
  61.          }  
  62.          long end_time=System.currentTimeMillis();  
  63.          System.out.println("end:"+(end_time-begin_time));  
  64.     }  
  65.   
  66. }  
  67. span>  

四、部署endpoint

部署endpoint有两种方法,第一种通过修改hbase.site.xml文件,实现对所有表加载这个endpoint;第二张通过alter表,实现对某一张表加载这个endpoint;

1、修改hbase.site.xml

在hbase.site.xml中添加如下内容

[html]  view plain copy
  1. <span style="font-family:SimSun;font-size:14px;"><property>  
  2.     <name>hbase.coprocessor.region.classesname>  
  3.     <value>com.cxk.coprocessor.test.RowCountEndpointvalue>  
  4.     <description>A comma-separated list of Coprocessors that are loaded by  
  5.     default. For any override coprocessor method from RegionObservor or  
  6.     Coprocessor, these classes' implementation will be called  
  7.     in order. After implement your own  
  8.     Coprocessor, just put it in HBase's classpath and add the fully  
  9.     qualified class name here.  
  10.     description>  
  11.   property>span>  

2、hbase shell alter表

A、将CXKTestProtos.java和RowCountEndpoint.java打成jar放到hdfs上;

B、

[html]  view plain copy
  1. <span style="font-family:SimSun;font-size:14px;">disable 'test'span>  

C、

[html]  view plain copy
  1. <span style="font-family:SimSun;font-size:14px;">alter 'test','coprocessor'=>'hdfs:///user/hadoop/test/coprocessor/cxkcoprocessor.1.01.jar|com.cxk.coprocessor.test.RowCountEndpoint|1001|arg1=1,arg2=2'span>  
D、
[html]  view plain copy
  1. <span style="font-family:SimSun;font-size:14px;">enable 'test'span>  

五、运行客户端

将TestEndPoint.java 打成jar,通过以下命令运行

[html]  view plain copy
  1. <span style="font-family:SimSun;font-size:14px;">java -jar test.cxk.endpiont.1.03.jar ip1 ip2 testspan>  

ps:如果eclipse可以直接调试hadoop,可直接运行测试类。


你可能感兴趣的:(hbase,hadoop集群,hbase,rowcount,hbase,Hadoop,rowcount)