进入到hbase shell , 执行list、version 等命令都一切正常,但执行写入操作例如新建表create 时,会一直卡住也没有报错信息。
于是乎上百度进行搜索原因,发现这种情况出现频率还挺高,看了几条博客。答题意思就是说,hbase 依赖的hdfs 进入了安全模式,解决方案是手动退出安全模式。
具体命令如下:
// 退出安全模式
hdfs dfsadmin -safemode leave
// 查询安全模式状态
hdfs dfsadmin -safemode get
退出安全模式之后发现还是卡住,上ambari 的AdminUI 上查看HBase 的情况发现region server 全挂掉了,遂重启Hbase 服务,然后进入hbase shell 操作一切正确。
在hbase shell 上操作一切正常,但通过hbase-client 进行访问操作就会卡住。
hbase 依赖:
org.apache.hbase
hbase-client
2.0.2
连接代码:
public class HBaseDemo
{
private static final String TABLE_NAME = "table1";
private static final String CF_DEFAULT = "cf1";
private static final byte[] QUALIFIER = "data1".getBytes();
private static final byte[] ROWKEY = "1".getBytes();
private static Configuration config;
private static final String zk="172.18.100.76:2181,172.18.100.77:2181,172.18.100.78:2181";
static {
config= HBaseConfiguration.create();
}
public static void main(String[] args)
{
config.set(HConstants.ZOOKEEPER_QUORUM, zk);
Connection connection = null;
try {
connection = ConnectionFactory.createConnection(config);
HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf(TABLE_NAME));
tableDescriptor.addFamily(new HColumnDescriptor(CF_DEFAULT));
System.out.print("Creating table. ");
Admin admin = connection.getAdmin();
// 获取所有的表名
for (TableName tableName : admin.listTableNames())
{
System.out.println(new String(tableName.getName(), "utf8"));
}
admin.createTable(tableDescriptor);
System.out.println(" Done.");
Table table = connection.getTable(TableName.valueOf("t"));
try {
Put put = new Put(ROWKEY);
put.addColumn(CF_DEFAULT.getBytes(), QUALIFIER, "this is value".getBytes());
table.put(put);
Get get = new Get(ROWKEY);
Result r = table.get(get);
byte[] b = r.getValue(CF_DEFAULT.getBytes(), QUALIFIER); // returns current version of value
System.out.println(new String(b));
} finally {
if (table != null) table.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
故障分析:
使用idea 的zookeeper 插件连接上任一台机器的zookeeper, zookeeper 所有节点如下:发现hbase 的zk 根节点为/hbase-unsecure
查看hbase-client 源码:发现hbase-client 默认连接的zk 根节点为/hbase
public static final String DEFAULT_ZOOKEEPER_ZNODE_PARENT = "/hbase";
所以在代码中需指定zk的根节点,加入一行代码如下:
config.set(HConstants.ZOOKEEPER_ZNODE_PARENT, "/hbase-unsecure");
改过之后,代码前面部分读取全部表名一切正常,之后对表的操作都会抛出异常:
Caused by: org.apache.hadoop.hbase.ipc.RemoteWithExtrasException(org.apache.hadoop.hbase.security.AccessDeniedException):
org.apache.hadoop.hbase.security.AccessDeniedException: Insufficient permissions for user 'miaoqiao' (action=create)
由异常可知用户miaoqiao 没有create 的操作权限(这个miaoqiao是我本机的windows 用户名,程序默认以本机用户名访问),然后我就想hbase-client 有没有指定访问用户的配置,查找了一番发现没有。
在百度上找到了以下解决方案:
之后我注意到ambari 提供了一个ranger 组件就是用来管理hdfs 权限的,遂进入到ranger AdminUI 页面:
点击进入hbase 的权限管理,发现只有hbase 这一个用户有操作权限,遂新增用户,取名miaoqiao(我本机用户名),进入到hbase 授权页面进行授权,然后更新保存。
然后使用Java hbase-client 对hbase 的操作就一切正常了!!!