112.HBase Endpoint类型的Coprocessor开发与部署

112.1 准备环境

  • 下载Protobuf2.5.0版本的安装包:
https://github.com/google/protobuf/releases/download/v2.5.0/protobuf-2.5.0.tar.gz
  • 选择一台服务器安装Protobuf
[root@ip-186-31-5-38 ~]# wget https://github.com/google/protobuf/releases/download/v2.5.0/protobuf-2.5.0.tar.gz
  • 安装Protobuf所需要的依赖包
yum install -y autoconf automake libtool curl make g++ unzip gcc-c++
  • 解压protobuf-2.5.0.tar.gz
[root@ip-186-31-5-38 ~]# tar -zxvf protobuf-2.5.0.tar.gz
[root@ip-186-31-5-38 ~]# cd protobuf-2.5.0
[root@ip-186-31-5-38 protobuf-2.5.0]# ./configure --prefix=/usr/local/protobuf
[root@ip-186-31-5-38 protobuf-2.5.0]# make && make install
  • Protobuf环境变量配置
export PROTOBUF_HOME=/usr/local/protobuf
export PATH=$PROTOBUF_HOME/bin:$PATH
  • 环境变量生效
[root@ip-186-31-5-38 protobuf-2.5.0]# source /etc/profile
  • HBase测试表
create 'fayson_coprocessor', {NAME => 'info'}
put 'fayson_coprocessor','001','info:sales',12.3
put 'fayson_coprocessor','002','info:sales',24.5
put 'fayson_coprocessor','003','info:sales',10.5
put 'fayson_coprocessor','004','info:sales',11.5
put 'fayson_coprocessor','005','info:sales',10.5
put 'fayson_coprocessor','001','info:age',22
put 'fayson_coprocessor','002','info:age',33
put 'fayson_coprocessor','003','info:age',26
put 'fayson_coprocessor','004','info:age',28
put 'fayson_coprocessor','005','info:age',56

112.2 生成序列化类

  • MyFirstCoprocessor.proto文件
[root@ip-186-31-5-171 hbase-coprocessor]# vim MyFirstCoprocessor.proto 
syntax = "proto2";
option java_package = "com.cloudera.hbase.coprocessor.server";
option java_outer_classname = "MyFirstCoprocessor";
option java_generic_services = true;
option java_generate_equals_and_hash = true;
option optimize_for = SPEED;
message MyCoprocessRequest {
    required string family = 1;
    required string columns = 2;
}
message MyCoprocessResponse {
    required int64 count = 1;
    required double maxnum = 3;
    required double minnum = 4;
    required double sumnum = 5;
}
service AggregationService {
  rpc getAggregation(MyCoprocessRequest)
    returns (MyCoprocessResponse);
}
  • 生成Java类
[root@ip-186-31-5-38 hbase-coprocessor]# protoc --java_out=./ MyFirstCoprocessor.proto 
[root@ip-186-31-5-38 hbase-coprocessor]# ll
total 4
drwxr-xr-x 3 root root  22 May 14 16:34 com
-rw-r--r-- 1 root root 609 May 14 16:33 MyFirstCoprocessor.proto
[root@ip-186-31-5-38 hbase-coprocessor]# 

112.3 服务端实现

  • pom.xml文件内容
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-client</artifactId>
    <version>2.6.0-cdh5.11.2</version>
</dependency>
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-common</artifactId>
    <version>2.6.0-cdh5.11.2</version>
</dependency>
<dependency>
    <groupId>org.apache.hbase</groupId>
    <artifactId>hbase-client</artifactId>
    <version>1.2.0-cdh5.11.2</version>
</dependency>
<dependency>
    <groupId>org.apache.hbase</groupId>
    <artifactId>hbase-examples</artifactId>
    <version>1.2.0-cdh5.11.2</version>
</dependency>
<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>2.5.0</version>
</dependency>
  • Protobuf生成的java类拷贝至指定的包目录下与MyFirstCoprocessor.proto文件指定的java_package包目录一致
  • MyFirstCoprocessorEndpoint实现类
package com.cloudera.hbase.coprocessor.server;
import com.google.protobuf.RpcCallback;
import com.google.protobuf.RpcController;
import com.google.protobuf.Service;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
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.CoprocessorService;
import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
import org.apache.hadoop.hbase.protobuf.ResponseConverter;
import org.apache.hadoop.hbase.regionserver.InternalScanner;
import org.apache.hadoop.hbase.util.Bytes;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class MyFirstCoprocessorEndPoint extends MyFirstCoprocessor.AggregationService implements Coprocessor, CoprocessorService {
    protected static final Log log = LogFactory.getLog(MyFirstCoprocessorEndPoint.class);
    private RegionCoprocessorEnvironment env;
    @Override
    public void getAggregation(RpcController controller, MyFirstCoprocessor.MyCoprocessRequest request, RpcCallback<MyFirstCoprocessor.MyCoprocessResponse> done) {
        Scan scan = new Scan();
        scan.addFamily(Bytes.toBytes(request.getFamily()));
        //传入列的方式   sales:MAX,sales:MIN,sales:AVG,slaes:SUM,sales:COUNT
        String colums = request.getColumns();
        //记录所有要扫描的列
        Map<String, List<String>> columnMaps = new HashedMap();
        for (String columnAndType : colums.split(",")) {
            String column = columnAndType.split(":")[0];
            String type = columnAndType.split(":")[1];
            List<String> typeList = null;
            if (columnMaps.containsKey(column)) {
                typeList = columnMaps.get(column);
            } else {
                typeList = new ArrayList<>();
                //将column添加到Scan中
                scan.addColumn(Bytes.toBytes(request.getFamily()), Bytes.toBytes(column));
            }
            typeList.add(type);
            columnMaps.put(column, typeList);
        }
        InternalScanner scanner = null;
        MyFirstCoprocessor.MyCoprocessResponse response = null;
        Double max = null;
        Double min = null;
        Double sumVal = null;
        long counter = 0L;
        try {
            scanner = this.env.getRegion().getScanner(scan);
            List<Cell> results = new ArrayList<>();
            boolean hasMore = false;
            scanner = env.getRegion().getScanner(scan);
            do {
                hasMore = scanner.next(results);
                if (results.size() > 0) {
                    ++counter;
                }
                log.info("counter:" + counter);
                log.info("results size:" + results.size());
                for (Cell cell : results) {
                    String column = Bytes.toString(CellUtil.cloneQualifier(cell));
                    log.info("Column Name: " + column);
                    log.info("Cell Value:" + new String(CellUtil.cloneValue(cell)));
                    Double temp = Double.parseDouble(new String(CellUtil.cloneValue(cell)));
                    if (columnMaps.containsKey(column)) {
                        List<String> types = columnMaps.get(column);
                        for (String type : types) {
                            switch (type.toUpperCase()) {
                                case "MIN":
                                    min = min != null && (temp == null || compare(temp, min) >= 0) ? min : temp;
                                    log.info("MIN Value: " + min.doubleValue());
                                    break;
                                case "MAX":
                                    max = max != null && (temp == null || compare(temp, max) <= 0) ? max : temp;
                                    break;
                                case "SUM":
                                    if (temp != null) {
                                        sumVal = add(sumVal, temp);
                                    }
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
                results.clear();
            } while (hasMore);
            response = MyFirstCoprocessor.MyCoprocessResponse.newBuilder()
                    .setMaxnum(max!=null?max.doubleValue():Double.MAX_VALUE)
                    .setMinnum(min!=null?min.doubleValue():Double.MIN_NORMAL)
                    .setCount(counter)
                    .setSumnum(sumVal!=null?sumVal.doubleValue():Double.MIN_NORMAL).build();
        } catch (IOException e) {
            e.printStackTrace();
            ResponseConverter.setControllerException(controller, e);
        } finally {
            if (scanner != null) {
                try {
                    scanner.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        done.run(response);
    }
    public static int compare(Double l1, Double l2) {
        if (l1 == null ^ l2 == null) {
            return l1 == null ? -1 : 1; // either of one is null.
        } else if (l1 == null)
            return 0; // both are null
        return l1.compareTo(l2); // natural ordering.
    }
    public double divideForAvg(Double d1, Long l2) {
        return l2 != null && d1 != null?d1.doubleValue() / l2.doubleValue():0.0D / 0.0;
    }
    public Double add(Double d1, Double d2) {
        return d1 != null && d2 != null ? Double.valueOf(d1.doubleValue() + d2.doubleValue()) : (d1 == null ? d2 : d1);
    }
    @Override
    public void start(CoprocessorEnvironment coprocessorEnvironment) throws IOException {
        if (coprocessorEnvironment instanceof RegionCoprocessorEnvironment) {
            this.env = (RegionCoprocessorEnvironment) coprocessorEnvironment;
        } else {
            throw new CoprocessorException("Must be loaded on a table region!");
        }
    }
    @Override
    public void stop(CoprocessorEnvironment coprocessorEnvironment) throws IOException {
    }
    @Override
    public Service getService() {
        return this;
    }
}

112.4 客户端实现

  • MyFirstCoprocessExample.java类
package com.cloudera.hbase.coprocessor.client;
import com.cloudera.hbase.coprocessor.server.MyFirstCoprocessor;
import com.cloudera.hbase.coprocessor.server.MyFirstCoprocessorEndPoint;
import com.google.common.util.concurrent.AtomicDouble;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.Coprocessor;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.client.coprocessor.Batch;
import org.apache.hadoop.hbase.client.coprocessor.DoubleColumnInterpreter;
import org.apache.hadoop.hbase.ipc.BlockingRpcCallback;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicLong;

public class MyFirstCoprocessExample {
    public static void main(String[] args) {
        String table_name = "fayson_coprocessor";
        //初始化HBase配置
        Configuration configuration = HBaseConfiguration.create();
        configuration.set("hbase.zookeeper.property.clientPort", "2181");
        configuration.setStrings("hbase.zookeeper.quorum", "ip-186-31-5-38.ap-southeast-1.compute.internal,ip-186-31-8-230.ap-southeast-1.compute.internal,ip-186-31-5-171.ap-southeast-1.compute.internal");
        try {
            //创建一个HBase的Connection
            Connection connection = ConnectionFactory.createConnection(configuration);
            TableName tableName = TableName.valueOf(table_name);
            if(!connection.getAdmin().tableExists(tableName)) {
                System.out.println(table_name + "does not exist....");
                System.exit(0);
            }
            Table table = connection.getTable(tableName);
            //删除表上的协处理器
            deleteCoprocessor(connection, table, MyFirstCoprocessorEndPoint.class);
            //为指定的表添加协处理器
            String hdfspath = "hdfs://nameservice3/hbase/coprocessor/hbase-demo-1.0-SNAPSHOT.jar";
            setupToExistTable(connection, table, hdfspath, MyFirstCoprocessorEndPoint.class);
            //客户端调用Region端的协处理器
            execFastEndpointCoprocessor(table, "info", "sales:MAX,sales:MIN,sales:AVG,sales:SUM,sales:COUNT");
            //关闭连接
            connection.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 删除HBase表上的协处理器
     * @param connection
     * @param table
     * @param cls
     */
    public static void deleteCoprocessor(Connection connection, Table table, Class<?>... cls) {
        System.out.println("begin delete " + table.getName().toString() + " Coprocessor......");
        try {
            HTableDescriptor hTableDescriptor = table.getTableDescriptor();
            for(Class cass : cls) {
                hTableDescriptor.removeCoprocessor(cass.getCanonicalName());
            }
            connection.getAdmin().modifyTable(table.getName(), hTableDescriptor);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("end delete " + table.getName().toString() + " Coprocessor......");
    }
    /**
     *
     * @param connection
     * @param table
     * @param jarPath
     * @param cls
     */
    public static void setupToExistTable(Connection connection, Table table, String jarPath, Class<?>... cls) {
        try {
            if(jarPath != null && !jarPath.isEmpty()) {
                Path path = new Path(jarPath);
                HTableDescriptor hTableDescriptor = table.getTableDescriptor();
                for(Class cass : cls) {
                    hTableDescriptor.addCoprocessor(cass.getCanonicalName(), path, Coprocessor.PRIORITY_USER, null);
                }
                connection.getAdmin().modifyTable(table.getName(), hTableDescriptor);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 效率最高的方式,在方式二的基础上优化
     * 通过HBase的coprocessorService(Class, byte[],byte[],Batch.Call,Callback<R>)方法获取表的总条数
     * @param table HBase表名
     * @return 返回表的总条数
     */
    public static long execFastEndpointCoprocessor(Table table, String family, String columns) {
        long start_t = System.currentTimeMillis();
        //定义总的 rowCount 变量
        AtomicLong totalRowCount = new AtomicLong();
        AtomicDouble maxValue = new AtomicDouble(Double.MIN_VALUE);
        AtomicDouble minValue = new AtomicDouble(Double.MAX_VALUE);
        AtomicDouble sumValue = new AtomicDouble();
        try {
            Batch.Callback<MyFirstCoprocessor.MyCoprocessResponse> callback = new Batch.Callback<MyFirstCoprocessor.MyCoprocessResponse>() {
                @Override
                public void update(byte[] bytes, byte[] bytes1, MyFirstCoprocessor.MyCoprocessResponse myCoprocessResponse) {
                    //更新Count值
                    totalRowCount.getAndAdd(myCoprocessResponse.getCount());
                    //更新最大值
                    if(myCoprocessResponse.getMaxnum() > maxValue.doubleValue()) {
                        maxValue.compareAndSet(maxValue.doubleValue(), myCoprocessResponse.getMaxnum());
                    }
                    //更新最小值
                    if(myCoprocessResponse.getMinnum() < minValue.doubleValue()) {
                        minValue.compareAndSet(minValue.doubleValue(), myCoprocessResponse.getMinnum());
                    }
                    //更新求和
                    sumValue.getAndAdd(myCoprocessResponse.getSumnum());
                }
            };
            table.coprocessorService(MyFirstCoprocessor.AggregationService.class, null, null, new Batch.Call<MyFirstCoprocessor.AggregationService, MyFirstCoprocessor.MyCoprocessResponse>() {
                @Override
                public MyFirstCoprocessor.MyCoprocessResponse call(MyFirstCoprocessor.AggregationService aggregationService) throws IOException {
                    MyFirstCoprocessor.MyCoprocessRequest requet = MyFirstCoprocessor.MyCoprocessRequest.newBuilder().setFamily(family).setColumns(columns).build();
                    BlockingRpcCallback<MyFirstCoprocessor.MyCoprocessResponse> rpcCallback = new BlockingRpcCallback<>();
                    aggregationService.getAggregation(null, requet, rpcCallback);
                    MyFirstCoprocessor.MyCoprocessResponse response = rpcCallback.get();
                    return response;
                }
            }, callback);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("耗时:" + (System.currentTimeMillis() - start_t));
        System.out.println("totalRowCount:" + totalRowCount.longValue());
        System.out.println("maxValue:" + maxValue.doubleValue());
        System.out.println("minValue:" + minValue.doubleValue());
        System.out.println("sumValue:" + sumValue.doubleValue());
        System.out.println("avg:" + new DoubleColumnInterpreter().divideForAvg(sumValue.doubleValue(), totalRowCount.longValue()));
        return totalRowCount.longValue();
    }
}

112.5 部署及调用

  • mvn编译
mvn clean package
  • 上传HDFS的/hbase/coprocessor目录
[root@ip-186-31-5-38 ~]# export HADOOP_USER_NAME=hbase         
[root@ip-186-31-5-38 ~]# hadoop fs -mkdir -p /hbase/coprocessor
[root@ip-186-31-5-38 ~]# hadoop fs -put hbase-demo-1.0-SNAPSHOT.jar /hbase/coprocessor
[root@ip-186-31-5-38 ~]# hadoop fs -ls /hbase/coprocessor

大数据视频推荐:
CSDN
大数据语音推荐:
ELK7 stack开发运维
企业级大数据技术应用
大数据机器学习案例之推荐系统
自然语言处理
大数据基础
人工智能:深度学习入门到精通

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个错误提示是因为HBase RegionServer加载了一个或多个协处理器(Coprocessor),其中至少一个协处理器抛出了异常,导致RegionServer崩溃。在这个错误提示中,协处理器的名称是MultiRowMutationEndpoint。 协处理器是一种机制,可以让HBase用户在RegionServer上运行自定义代码来处理HBase的数据。协处理器可以用来实现各种功能,比如数据过滤、数据转换、数据合并等。但是,协处理器也可能出现问题,导致RegionServer运行异常。常见的协处理器问题包括: 1. 协处理器代码有缺陷,导致异常抛出。 2. 协处理器与HBase版本不兼容。 3. 协处理器配置不正确,导致异常抛出。 针对这个错误,你可以尝试以下解决方法: 1. 检查协处理器代码:协处理器代码可能有缺陷,导致抛出异常。可以检查协处理器代码,修复问题,并重新加载协处理器。 2. 检查协处理器与HBase版本是否兼容:协处理器可能与HBase版本不兼容,需要检查协处理器与HBase版本的兼容性,并采取相应的措施,如升级协处理器或者降低HBase版本。 3. 检查协处理器配置:协处理器配置可能不正确,导致异常抛出。可以检查协处理器配置,确保配置正确。 4. 禁用协处理器:如果无法解决协处理器问题,可以尝试禁用协处理器,看是否可以解决问题。可以在HBase Shell中使用disable命令禁用协处理器。 希望以上解决方法能帮助你解决问题。如果还有其他问题,请随时向我提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值