java连接hbase优化

在使用java连接hbase的时候,首次初始化配置的时间大概是10s左右,所以会造成一些操作比较耗时,会自动断开连接。出错的环境如下,要实现一个订单的评论功能,评论有文件内容和图片,在后台首先要判断该用户的信息是否正确,然后才可以继续执行下一步的评论操作;所以这时候使用到mysql数据库。

用户信息正确之后,接下来就是执行图片的存储,这里使用到了hbase分布式数据库,在存储数据到hbase之前,要耗费大概10s的时间来进行hbase的初始化连接;然后再把文件存储到hbase的位置保存到mysql数据库中,这就导致了mysql连接中断。

虽然以上错误只是在hbase的第一次初始化的时候出现,但是为了杜绝以上的错误,就必须在tomcat启动的过程中,自动加载Hbase的静态类,以便在static静态块中对hbase连接进行一个初始化操作。


以下是解决的步骤。

(1)编写Hbase操作的工具类,如下所示

package com.yitian.zhishang.utils;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.util.Bytes;

import com.sun.org.apache.bcel.internal.generic.NEW;



/**
 * 操作hbase数组库工具类
 * function 主要用来存取图片
 * @author canye
 * 2016年3月18日星期五
 */
public class HbaseOperatorUtil {
  private static Configuration configuration; //配置对象
  private final static String IMAGE_TABLE_NAME = "image";//存储图片的表
  private final static String IMAGE_COLUMN_FAMILY = "data" ;//列族名
  private final static String QUALIFIER = "tupian"; //列的标识符
 
  //获取图片的链接地址
  public final static String WEB_IMAGE_PATH ="http://192.168.3.230/SpringMVCAndMybatis/download/downloadChatFile.action?hadoopFileName=";
 
  //初始化hbase
  static{
    
      //给configuration赋值
      configuration = HBaseConfiguration.create();
      //设置zookeeper的节点信息(主机名)
      configuration.set("hbase.zookeeper.quorum", "yitian1,yitian2,yitian3");
      //设置zookeeper相互通信的端口号
      configuration.set("hbase.zookeeper.property.clientPort", "2181");
      
      //判断保存图片的表是否创建了,如果没有则创建,调用以下函数
      createHbaseTable(IMAGE_TABLE_NAME, IMAGE_COLUMN_FAMILY);
    
      //2016年4月29日添加,提高性能测试
      try {
        HTable.setRegionCachePrefetch(IMAGE_TABLE_NAME.getBytes(), true);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
 
  }
 
  /*
   * 创建hbase表
   * @param tableName 要创建的表的表名
   * @param columnFamily 要创建的表的列族名
   *
   */
  public static void createHbaseTable(String tableName,String columnFamily){
      
      try {
          //首先要创建一个hbase数据库管理员对象
          HBaseAdmin admin = new HBaseAdmin(configuration);
          //判断要创建的表是否存在,如果存在则不再创建,如果不存在则要创建
          if(admin.tableExists(tableName)){ //表存在了,则不创建
             System.out.println("该表"+tableName+"已经存在了!");  
          }else {//表不存在,需要创建
              //创建一个表的描述
            HTableDescriptor descriptor = HTableDescriptor.parseFrom(Bytes.toBytes(tableName));
            //在描述对象添加一个列族
            descriptor.addFamily(new HColumnDescriptor(columnFamily));
            //创建表
            admin.createTable(descriptor);
            System.out.println("表"+tableName+"创建成功!");
        }
          admin.close(); //关闭管理员对象
    } catch (Exception e) {
        e.printStackTrace();
    }
  }
 
  /*
   * 插入数据
   * @param  rowId 记录的主键
   * @param  data  要保存的数据
   */
   public static void insertHaseData(String rowId,byte[] data) throws Exception{
       //获取表对象
       HTable table = new HTable(configuration, IMAGE_TABLE_NAME);
       
       //创建put对象
       Put put = new Put(Bytes.toBytes(rowId));
        
       //添加数据
       put.add(Bytes.toBytes("data"),Bytes.toBytes("tupian"), data);
       
       //put数据到table对象
       table.put(put);
      
        //提交数据
       table.flushCommits();
       //关闭table
       table.close();

   }
   
   
   /*
    * 根据主键获取数据
    * @param rowId  行的主键
    * @return data 返回的图片数据的字节数组
    */
   public static byte[] getHbaseData(String rowId)throws Exception{
       //创建一个table对象
       HTable table = new HTable(configuration, IMAGE_TABLE_NAME);
       //创建一个Get对象
       Get get = new Get(Bytes.toBytes(rowId));
       //设置获取的版本数
       get.setMaxVersions(5);
       
       //获取结果集对象
       Result result = table.get(get);
       
      //获取图片的二进制数据
      byte[] data = result.getValue(Bytes.toBytes(IMAGE_COLUMN_FAMILY),Bytes.toBytes(QUALIFIER));
       
      System.out.println("Length of file is "+data.length+" byte");
      
       //关闭table
       table.close();
       
      //返回结果
      return data;
   }
   
   /*
    * 删除单个数据
    * @param rowKey  行主键
    */
   public static void deleteSingleHbaseData(String rowKey) throws Exception{
       //创建一个Htable对象
       HTable table = new HTable(configuration, IMAGE_TABLE_NAME);
       //创建Delete对象
       Delete delete = new Delete(rowKey.getBytes());
       //删除记录
       table.delete(delete);
       //关闭table
       table.close();
   }
 
}


(2)实现ServletContextListener接口,并在该接口的contextInitialized中对上述的Hbase类进行加载

package com.yitian.zhishang.utils.init;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
 * tomcat启动时要自动加载的相关操作
 * @author canye
 * @date 2016年7月14日星期四
 */
public class MyInitListener implements ServletContextListener {

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
    }

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        //因为首次初始化hbase的连接比较耗时,所以打算随着tomcat启动就自动加载hbase的工具类
        try {
            Class.forName("com.yitian.zhishang.utils.HbaseOperatorUtil");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}


(3)在web.xml文件中添加以下的内容

<!-- hbase连接优化 -->
  <listener>
    <listener-class>com.yitian.zhishang.utils.init.MyInitListener</listener-class>
  </listener>


总结:项目部署到tomcat的时候,首先检查web.xml文件,然后加载MyInitListener监听器,并执行contextInitialized方法,在该方法中通过 Class.forName("com.yitian.zhishang.utils.HbaseOperatorUtil");加载Hbase的工具类,Hbase在被加载后,就自动执行静态代码块中的代码,实现连接hbase的初始化操作。


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值