Hadoop生态圈-注册并加载协处理器(coprocessor)的三种方式

                                          作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

  到目前为止,大家已经掌握了如何使用过滤器来减少服务器端通过网络返回到客户端的数据量。HBase中还有一些特性让用户甚至可以把一部分计算也移动到数据的存放端,他就是本篇博客的主角:协处理器(coprocessor)。

一.协处理器简介

  使用客户端API,配合筛选机制,例如,使用过滤器或限制列族的范围,都可以控制被返回到客户端的数据量。如果可以更进一步优化会更好,例如,数据的处理流程直接存放到服务器端执行,然后仅返回一个小的处理结果集。这类似于一个小型的MapReduce框架,该框架将工作分发到整个集群。

  协处理器运行用户在region服务器上运行自己的代码,更准确的说是允许用户执行region级的操作,并且可以使用RDBMS中触发器(trigger)类似的功能。在客户端,用户不用关心操作具体在哪里执行,HBase的分布式框架会帮助用户把这些工作变得透明。这里用户可以监听一些隐式的事件,并利用其来完成一些辅助任务。如果这还不够,用户还可以自己扩展现有的RPC协议引用自己的调用,这些调用有客户端出阿发,并在服务器端执行。

  协处理器框架已经提供了一些类,用户可以通过继承这些类来扩展自己的功能。这些类主要分为两大类,即observer和endpoint。以下是各个功能的简要介绍。

1>.observer

  这一类协处理器与触发器(trigger)类似:回调函数(也被称作钩子函数,hook)在一些特定时间发生时被执行。这些时间包括一些用户产生的事件,也包括服务器内部自动产生的事件,也包括服务器端内部自动产生的事件。协处理器框架提供的接口如下所示:

    a>.RegionObserver:用户可以用这种的处理器处理数据修改时间,他们与表的region联系紧密;

    b>.MasterObserve:可以被用作管理或DDL类型的操作,这些是集群级事件;

    c>.WALObserver:提供控制WAL的钩子函数;

  observer提供了一些设计好的回调函数,每个操作在集群服务器端都可以被调用。

2>.endpoint

  除了事件处理之外还需要将用户自定义操作添加到服务器端。用户代码可以被部署到管理数据的服务器端,例如,做一些服务器端计算的工作。endpoint通过添加一些远程过程调用来动态扩展RPC协议。可以把他们理解为与RDBMS中类似的存储过程,endpoint可以与observer的实现组合起来直接作用于服务器端的状态。

二.RegionObserver类

  在region级别中介绍的Coprocessor第一个子类是RegionObserver类。从名字中可以看出它属于observer协处理器:当一个特定的region级别的操作发生时,他们的钩子函数会被触发。

  BaseRegionObserver类可以作为所有用户实现监听类型协处理器的基类。它实现了所有RegionObserver接口的空方法,所有在默认情况下基础这个类的协处理器没有任何功能。用户需要重载他们干星期的方法实现自己的功能。接下来我们体验一下observer。

1>.编写MyRegionObserver.java 文件

 /*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Hadoop%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.coprocessor; import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CoprocessorEnvironment;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Durability;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.coprocessor.BaseRegionObserver;
import org.apache.hadoop.hbase.coprocessor.ObserverContext;
import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
import org.apache.hadoop.hbase.regionserver.wal.WALEdit; import java.io.*;
import java.util.List; public class MyRegionObserver extends BaseRegionObserver {
File f = new File("/home/yinzhengjie/coprocessor.log"); @Override
public void start(CoprocessorEnvironment e) throws IOException {
super.start(e); if(!f.exists()){
f.createNewFile();
}
FileOutputStream fos = new FileOutputStream( f, true);
fos.write("this is a start function\n".getBytes());
fos.close();
} @Override
public void stop(CoprocessorEnvironment e) throws IOException {
super.stop(e);
if(!f.exists()){
f.createNewFile();
}
FileOutputStream fos = new FileOutputStream(f, true);
fos.write("this is a stop function\n".getBytes());
fos.close();
} @Override
public void postFlush(ObserverContext<RegionCoprocessorEnvironment> e) throws IOException {
super.postFlush(e);
if(!f.exists()){
f.createNewFile();
} //
String table = e.getEnvironment().getRegionInfo().getTable().getNameAsString(); FileOutputStream fos = new FileOutputStream(f, true);
fos.write(("this is a flush function, table: " + table + "被刷新了\n ").getBytes());
fos.close(); } @Override
public void postGetOp(ObserverContext<RegionCoprocessorEnvironment> e, Get get, List<Cell> results) throws IOException {
super.postGetOp(e, get, results);
if(!f.exists()){
f.createNewFile();
}
//通过put得到操作行
String row = new String(get.getRow()); //
String table = e.getEnvironment().getRegionInfo().getTable().getNameAsString(); FileOutputStream fos = new FileOutputStream(f, true);
fos.write(("this is a get function, table: " + table + ",row: " + row + "发生了修改\n ").getBytes());
fos.close();
} @Override
public void postPut(ObserverContext<RegionCoprocessorEnvironment> e, Put put, WALEdit edit, Durability durability) throws IOException {
super.postPut(e, put, edit, durability); if(!f.exists()){
f.createNewFile();
} //通过put得到操作行
String row = new String(put.getRow()); //
String table = e.getEnvironment().getRegionInfo().getTable().getNameAsString(); FileOutputStream fos = new FileOutputStream(f, true);
fos.write(("this is a put function, table: " + table + ",row: " + row + "发生了修改\n ").getBytes());
fos.close(); } @Override
public void postDelete(ObserverContext<RegionCoprocessorEnvironment> e, Delete delete, WALEdit edit, Durability durability) throws IOException {
super.postDelete(e, delete, edit, durability); if(!f.exists()){
f.createNewFile();
}
//通过put得到操作行
String row = new String(delete.getRow()); //
String table = e.getEnvironment().getRegionInfo().getTable().getNameAsString(); FileOutputStream fos = new FileOutputStream(f, true);
fos.write(("this is a delete function, table: " + table + ",row: " + row + "发生了修改\n ").getBytes());
fos.close();
}
}

2>.将以上代码进行打包操作,并将其放置/soft/hbase/lib下。并关闭hbase

3>.注册(/soft/hbase/conf/hbase-site.xml),目的是使用咱们写的jar包。

4>.同步文件

[yinzhengjie@s101 ~]$ more `which xrsync.sh`
#!/bin/bash
#@author :yinzhengjie
#blog:http://www.cnblogs.com/yinzhengjie
#EMAIL:y1053419035@qq.com #判断用户是否传参
if [ $# -lt 1 ];then
echo "请输入参数";
exit
fi #获取文件路径
file=$@ #获取子路径
filename=`basename $file` #获取父路径
dirpath=`dirname $file` #获取完整路径
cd $dirpath
fullpath=`pwd -P` #同步文件到DataNode
for (( i=102;i<=105;i++ ))
do
#使终端变绿色
tput setaf 2
echo =========== s$i %file ===========
#使终端变回原来的颜色,即白灰色
tput setaf 7
#远程执行命令
rsync -lr $filename `whoami`@s$i:$fullpath
#判断命令是否执行成功
if [ $? == 0 ];then
echo "命令执行成功"
fi
done
[yinzhengjie@s101 ~]$

[yinzhengjie@s101 ~]$ more `which xrsync.sh`

5>.启动hbase

[yinzhengjie@s101 ~]$ start-hbase.sh
starting master, logging to /soft/hbase/bin/../logs/hbase-yinzhengjie-master-s101.out
Java HotSpot(TM) -Bit Server VM warning: ignoring option PermSize=128m; support was removed in 8.0
Java HotSpot(TM) -Bit Server VM warning: ignoring option MaxPermSize=128m; support was removed in 8.0
s104: starting regionserver, logging to /soft/hbase/bin/../logs/hbase-yinzhengjie-regionserver-s104.out
s103: starting regionserver, logging to /soft/hbase/bin/../logs/hbase-yinzhengjie-regionserver-s103.out
s102: starting regionserver, logging to /soft/hbase/bin/../logs/hbase-yinzhengjie-regionserver-s102.out
s104: Java HotSpot(TM) -Bit Server VM warning: ignoring option PermSize=128m; support was removed in 8.0
s104: Java HotSpot(TM) -Bit Server VM warning: ignoring option MaxPermSize=128m; support was removed in 8.0
s103: Java HotSpot(TM) -Bit Server VM warning: ignoring option PermSize=128m; support was removed in 8.0
s103: Java HotSpot(TM) -Bit Server VM warning: ignoring option MaxPermSize=128m; support was removed in 8.0
s102: Java HotSpot(TM) -Bit Server VM warning: ignoring option PermSize=128m; support was removed in 8.0
s102: Java HotSpot(TM) -Bit Server VM warning: ignoring option MaxPermSize=128m; support was removed in 8.0
[yinzhengjie@s101 ~]$

6>.验证(get,put,还有delete等操作都会在“/home/yinzhengjie/coprocessor.log”文件中记录)

[yinzhengjie@s101 ~]$ hbase shell
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/soft/hbase-1.2./lib/slf4j-log4j12-1.7..jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/soft/hadoop-2.7./share/hadoop/common/lib/slf4j-log4j12-1.7..jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
HBase Shell; enter 'help<RETURN>' for list of supported commands.
Type "exit<RETURN>" to leave the HBase Shell
Version 1.2., rUnknown, Mon May :: CDT hbase(main)::> list
TABLE
ns1:t1
yinzhengjie:t1
row(s) in 0.2120 seconds => ["ns1:t1", "yinzhengjie:t1"]
hbase(main)::> create 'yinzhengjie:test','f1'
row(s) in 1.3300 seconds => Hbase::Table - yinzhengjie:test
hbase(main)::> list
TABLE
ns1:t1
yinzhengjie:t1
yinzhengjie:test
row(s) in 0.0080 seconds => ["ns1:t1", "yinzhengjie:t1", "yinzhengjie:test"]
hbase(main)::> put 'yinzhengjie:test','row1','f1:name','yinzhengjie'
row(s) in 0.1720 seconds hbase(main)::>

三.注册并加载协处理器的三种方式

1.使用XML文件进行注册(范围:世界级

  可以参考上面的配置。

2.使用代码,在创建表的时候,加载协处理器 (范围:表级)

  1>.将jar包上传到hdfs中

[yinzhengjie@s101 data]$ ll
total
-rw-r--r--. yinzhengjie yinzhengjie May : fastjson-1.2..jar
-rw-r--r--. yinzhengjie yinzhengjie Jun hbase-1.2.-bin.tar.gz
-rw-r--r--. yinzhengjie yinzhengjie Jun : MyHbase-1.0-SNAPSHOT.jar
-rw-r--r--. yinzhengjie yinzhengjie Jun : temptags.txt
-rw-r--r--. yinzhengjie yinzhengjie Jun : yinzhengjieCode-1.0-SNAPSHOT.jar
[yinzhengjie@s101 data]$ hdfs dfs -put MyHbase-1.0-SNAPSHOT.jar /myhbase.jar
[yinzhengjie@s101 data]$

  2>.停止HBase服务并清空之前的测试数据

[yinzhengjie@s101 data]$ stop-hbase.sh
stopping hbase................
[yinzhengjie@s101 data]$
[yinzhengjie@s101 data]$ more `which xcall.sh`
#!/bin/bash
#@author :yinzhengjie
#blog:http://www.cnblogs.com/yinzhengjie
#EMAIL:y1053419035@qq.com #判断用户是否传参
if [ $# -lt ];then
echo "请输入参数"
exit
fi #获取用户输入的命令
cmd=$@ for (( i=;i<=;i++ ))
do
#使终端变绿色
tput setaf
echo ============= s$i $cmd ============
#使终端变回原来的颜色,即白灰色
tput setaf
#远程执行命令
ssh s$i $cmd
#判断命令是否执行成功
if [ $? == ];then
echo "命令执行成功"
fi
done
[yinzhengjie@s101 data]$
[yinzhengjie@s101 data]$ xcall.sh rm -rf /home/yinzhengjie/coprocessor.log
============= s101 rm -rf /home/yinzhengjie/coprocessor.log ============
命令执行成功
============= s102 rm -rf /home/yinzhengjie/coprocessor.log ============
命令执行成功
============= s103 rm -rf /home/yinzhengjie/coprocessor.log ============
命令执行成功
============= s104 rm -rf /home/yinzhengjie/coprocessor.log ============
命令执行成功
============= s105 rm -rf /home/yinzhengjie/coprocessor.log ============
命令执行成功
[yinzhengjie@s101 data]$

  3>.编辑配置文件(将之前实现的配置删除,具体保留配置如下)

[yinzhengjie@s101 data]$ more /soft/hbase/conf/hbase-site.xml
<?xml version="1.0"?>
<configuration>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>hbase.rootdir</name>
<value>hdfs://mycluster/user/hbase</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/home/yinzhengjie/zookeeper</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>s102:,s103:,s104:</value>
</property> </configuration>
[yinzhengjie@s101 data]$

  4>.启动HBase并运行以下代码,创建ns1:observer表并指定加载协处理器

 /*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Hadoop%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.coprocessor; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory; public class AssignCopro { public static void main(String[] args) throws Exception { Configuration conf = HBaseConfiguration.create();
//先建立连接
Connection conn = ConnectionFactory.createConnection(conf);
Admin admin = conn.getAdmin();
//列描述符
HColumnDescriptor f1 = new HColumnDescriptor("f1");
HColumnDescriptor f2 = new HColumnDescriptor("f2");
HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("ns1:observer")); htd.addCoprocessor("cn.org.yinzhengjie.coprocessor.MyRegionObserver",
new Path("/myhbase.jar"), , null); //表中添加列族
htd.addFamily(f1);
htd.addFamily(f2);
admin.createTable(htd);
admin.close();
}
}

  5>.运行以下代码后,查看“/home/yinzhengjie/coprocessor.log”文件如下:

  查看HBase内容如下:

3.使用命令激活协处理器(范围:表级)

hbase(main)::> list
TABLE
ns1:observer
ns1:t1
yinzhengjie:t1
yinzhengjie:test
row(s) in 0.0210 seconds => ["ns1:observer", "ns1:t1", "yinzhengjie:t1", "yinzhengjie:test"]
hbase(main)::> disable 'ns1:t1'
row(s) in 2.3300 seconds hbase(main)::> alter 'ns1:t1', 'coprocessor'=>'hdfs://mycluster/myhbase.jar|cn.org.yinzhengjie.coprocessor.MyRegionObserver|0|'
Updating all regions with the new schema...
/ regions updated.
Done.
row(s) in 1.9440 seconds hbase(main)::> enable 'ns1:t1'
row(s) in 1.2570 seconds hbase(main)::>

  移除协处理器步骤如下:

Hadoop生态圈-注册并加载协处理器(coprocessor)的三种方式的更多相关文章

  1. ios网络学习------4 UIWebView的加载本地数据的三种方式

    ios网络学习------4 UIWebView的加载本地数据的三种方式 分类: IOS2014-06-27 12:56 959人阅读 评论(0) 收藏 举报 UIWebView是IOS内置的浏览器, ...

  2. 转 Velocity中加载vm文件的三种方式

    Velocity中加载vm文件的三种方式   velocitypropertiespath Velocity中加载vm文件的三种方式:    方式一:加载classpath目录下的vm文件 Prope ...

  3. Velocity中加载vm文件的三种方式

    Velocity中加载vm文件的三种方式: a.  加载classpath目录下的vm文件 /** * 初始化Velocity引擎 * --VelocityEngine是单例模式,线程安全 * @th ...

  4. iOS --- UIWebView的加载本地数据的三种方式

    UIWebView是IOS内置的浏览器,可以浏览网页,打开文档  html/htm  pdf   docx  txt等格式的文件.  safari浏览器就是通过UIWebView做的. 服务器将MIM ...

  5. 加载gif动画的三种方式

    GifView.h/** * 调用结束就开始播放动画,如果需要用户指定何时播放的话,只需要把timer的开始放到合适的位置.通过对CFDictonaryRaf 也就是gifProperties的改变, ...

  6. Spring加载Properties配置文件的三种方式

    一.通过 context:property-placeholder 标签实现配置文件加载 1) 用法: 1.在spring.xml配置文件中添加标签 <context:property-plac ...

  7. MVC加载分布页的三种方式

               第一种: @Html.Partial("_分部页")            第二种: @{ Html.RenderPartial("分部页" ...

  8. 加载xib文件的两种方式

    一.加载xib文件的两种方式 1.方法一(NewsCell是xib文件的名称) NSArray *objects = [[NSBundle mainBundle] loadNibNamed:@&quo ...

  9. Spring加载properties文件的两种方式

    在项目中如果有些参数经常需要修改,或者后期可能需要修改,那我们最好把这些参数放到properties文件中,源代码中读取properties里面的配置,这样后期只需要改动properties文件即可, ...

随机推荐

  1. 第一个scrim任务分布

    一.项目经理:郭健豪 二.scrim分工 杨广鑫.郭健豪:制作第一个精选页面布局,和代码实现.如:实现图书推荐布局中图书的排布,搜索框代码的实现,消息提示的跳转 李明.郑涛:实现第一个精选页面数据库的 ...

  2. Sprint4

    进展:今天一天满课,晚上也没有做什么,所以今天一天没什么进展. 燃尽图:

  3. 使用Crash工具查看一个TCP listen sock内存布局实例

    利用crash工具,我们可以很方便的查看正在运行内核的一些全局变量的数据结构,如TCP的ehash.bhash哈希桶,全局变量的查看比较简单.Crash工具还允许我们查看调用堆栈内部的局部变量,下面示 ...

  4. TCP连接 三次握手 四次挥手

    前言: TCP协议是面向连接.安全可靠.基于字节流的传输层协议,在进行http协议访问时就用到了tcp连接.在建立TCP连接时需要经历三次握手,断开连接时需要经历四次挥手.在此进行记录. 内容: TC ...

  5. 使用GatewayWorker 开发个即时聊天demo

    前言: 上手册以示尊重:https://www.kancloud.cn/walkor/gateway-worker/326138: https://www.cnblogs.com/fuqiang88/ ...

  6. Beta阶段——第一篇 Scrum 冲刺博客

    i. 提供当天站立式会议照片一张: ii. 每个人的工作 (有work item 的ID) (1) 昨天已完成的工作: 数据存储方式改本地存储为数据库存储. (2) 今天计划完成的工作: 账单和剩余舍 ...

  7. Beta阶段 敏捷冲刺day1

    一.提供当天站立式会议照片一张: 二. 每个人的工作 (有work item 的ID) (1) 昨天已完成的工作: (2) 今天计划完成的工作: 今天大家一起讨论了一下之后几天的任务,以及如何对网页进 ...

  8. 【Leetcode】143. Reorder List

    Question: Given a singly linked list L: L0→L1→…→Ln-1→Ln, reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… You ...

  9. python基础(四)文件操作和集合

    一.文件操作 对文件的操作分三步: 1.打开文件获取文件的句柄,句柄就理解为这个文件 2.通过文件句柄操作文件 3.关闭文件. 1.文件基本操作: f = open('file.txt','r') # ...

  10. PHP ini_set

    PHP ini_set用来设置php.ini的值,在函数执行的时候生效,对于虚拟空间来说,很方便,下面为大家介绍下此方法的使用   PHP ini_set用来设置php.ini的值,在函数执行的时候生 ...