前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何使用C++通过thrift访问HBase进行操作

如何使用C++通过thrift访问HBase进行操作

作者头像
create17
发布2019-05-14 10:58:22
3.1K0
发布2019-05-14 10:58:22
举报

每一个成功人士的背后,必定曾经做出过勇敢而又孤独的决定。

放弃不难,但坚持很酷~

前言

上周六,接了一个紧急任务,说实现使用 C++ 访问 HBase 进行操作。说是用 thrift 来实现。对于 C++ 来说,我真的是门外汉,但需求如此,皱着眉头也要把它实现。好歹在同事的帮助下,也是实现了 demo 示例,现在就把这两天的成果分享给大家。

版本

HDP:2.6.4.0

HBase:1.1.2

一、安装编译thrift

1. 准备工作

使用 yum 安装 Development Tools

yum -y groupinstall "Development Tools"

thrift 编译依赖于下面的工具,使用 yum 安装:

yum -y install automake libtool flex bison pkgconfig gcc-c++ boost-devel libevent-devel python-devel ruby-devel zlib-devel openssl-devel
2. 下载thrift安装包

为了生成依赖类库 /usr/local/include/thrift//usr/local/lib/ ,需要下载 thrift 源码包。本文使用 thrift 0.8.0 版本,通过以下地址下载后并解压。

cd /usr;wget http://archive.apache.org/dist/thrift/0.8.0/thrift-0.8.0.tar.gz
tar zxvf thrift-0.8.0.tar.gz;rm -rf thrift-0.8.0.tar.gz
3. 编译thrift
cd /usr/thrift-0.8.0
./configure --prefix=/usr/local/ --with-boost=/usr/local --with-libevent=/usr/local

命令执行完毕后,如下图所示:

编译 thrift ,执行如下命令:

make && make install

命令执行完毕后,如下图所示:

至此,thrift 0.8.0 就编译完成了。可执行 thrift -version 查看版本。

4. 检查相关文件是否存在

thrift编译成功后,会在 /usr/local/include/thrift//usr/local/lib/ 目录下生成相关文件,用于后面使用 g++ 工具编译 cpp 文件。如下图所示:

二、代码示例

1. 开启HBase thrift2

首先需要确保 HBase thrift2 服务正常运行。执行如下命令启动 HBase thrift2 服务:

/usr/hdp/2.6.4.0-91/hbase/bin/hbase-daemon.sh start thrift2

服务开启的默认端口号为 9090 ,可执行 netstat -ntlp | grep 9090 检测 thrift2 是否成功启动。

2. 生成c++相关文件
# 进入到hbase源码目录
cd /usr/hdp/2.6.4.0-91/hbase/include/thrift
# 在当前目录下生成gen-cpp目录,里面含有c++的相关文件
thrift --gen cpp hbase2.thrift

gen-cpp 目录下的文件列表如下图所示:

3. 编写客户端代码

创建 HbaseClient.cpp 文件(名称可自定义),向 hbase_test 表中插入一条数据,并打印指定 rowkey 的一行数据。代码内容如下所示:

#include "THBaseService.h"
#include <config.h>
#include <vector>
#include <transport/TSocket.h>
#include <transport/TBufferTransports.h>
#include <protocol/TBinaryProtocol.h>

using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::hadoop::hbase::thrift2;

using boost::shared_ptr;
int readdb(int argc, char** argv) {
    fprintf(stderr, "readdb start\n");
    int port = atoi(argv[2]);
    boost::shared_ptr<TSocket> socket(new TSocket(argv[1], port));
    boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
    boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
    try {
        transport->open();
        printf("open\n");
        THBaseServiceClient client(protocol);
        TResult tresult;
        TGet get;
        std::vector<TColumnValue> cvs;
        const std::string table("hbase_test");
        const std::string thisrow="1";
        //get data
        get.__set_row(thisrow);
        bool be = client.exists(table,get);
        printf("exists result value = %d\n", be);
        client.get(tresult,table,get);
        vector<TColumnValue> list=tresult.columnValues;
        std::vector<TColumnValue>::const_iterator iter;
        for(iter=list.begin();iter!=list.end();iter++) {
            printf("%s, %s, %s\n",(*iter).family.c_str(),(*iter).qualifier.c_str(),(*iter).value.c_str());
        }
        transport->close();
        printf("close\n");
    } catch (const TException &tx) {
        std::cerr << "ERROR(exception): " << tx.what() << std::endl;
    }
    fprintf(stderr, "readdb stop\n");
    return 0;
}

int writedb(int argc, char** argv){
    fprintf(stderr, "writedb start\n");
    int port = atoi(argv[2]);
    boost::shared_ptr<TSocket> socket(new TSocket(argv[1], port));
    boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
    boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
    try {
        transport->open();
        printf("open\n");
        THBaseServiceClient client(protocol);
        std::vector<TPut> puts;
        const std::string table("hbase_test");

        TPut put;
        std::vector<TColumnValue> cvs;
        //put data
        put.__set_row("1");
        TColumnValue tcv;
        tcv.__set_family("info");
        tcv.__set_qualifier("age");

        tcv.__set_value("24");
        cvs.insert(cvs.end(), tcv);
        put.__set_columnValues(cvs);
        puts.insert(puts.end(), put);

        client.putMultiple(table, puts);
        puts.clear();

        transport->close();
        printf("close\n");
    } catch (const TException &tx) {
        std::cerr << "ERROR(exception): " << tx.what() << std::endl;
    }
        fprintf(stderr, "writedb stop\n");
        return 0;
    }


int main(int argc, char **argv) {
    if(argc != 3) {
        fprintf(stderr, "param  is :XX ip port\n");
        return -1;
    }
    writedb(argc, argv);
    readdb(argc, argv);
    return 0;
}
4. 生成可执行的文件HbaseClient

使用 g++ 工具编译客户端代码,在 HbaseClient.cpp 所在的目录下执行以下命令:

g++ -DHAVE_NETINET_IN_H -o HbaseClient -I/usr/local/include/thrift -I./gen-cpp -L/usr/local/lib HbaseClient.cpp ./gen-cpp/hbase2_types.cpp ./gen-cpp/hbase2_constants.cpp ./gen-cpp/THBaseService.cpp -lthrift -g

命令参数说明:

  • -DHAVE_NETINET_IN_H:该参数解决编译时使用定义的文件内容。
  • -I/usr/local/include/thrift与-I./gen-cpp:g++会先在当前目录查找你所制定的头文件,如果没有找到,会回到缺省的头文件目录查找。使用-I参数指定目录,g++会先在你指定的目录中查找,然后再按常规的顺序查找。
  • -o HbaseClient:编译后输出HbaseClient文件。缺省状态下,编译后输出的文件为a.out。
  • -L/usr/local/lib:编译的时候,指定搜索库的路径。
  • -g:指示编译器,在编译时,产生调试信息。
5. 创建HBase表

在运行客户端之前,我们需要创建一个 hbase_test 表。创建表命令如下所示:

进入 HBase shell 命令行:

hbase shell

创建 hbase_test 表:

create 'hbase_test', {NAME => 'info'}

可执行 exit 命令退出命令行。

6. 运行客户端

可通过如下命令运行 HbaseClient 客户端:

# 在HbaseClient文件所在的当前目录下执行
./HbaseClient <thrift2_ip> <thrift2_port>

会出现错误:libthrift-0.8.0.so: cannot open shared object file。如下图所示:

解决方法:

需要配置环境变量。将export LD_LIBRARY_PATH=/usr/local/lib添加至/etc/profile文件中,如下图所示:

最后,执行 source /etc/profile 命令,使环境变量立即生效。

再执行 ./HbaseClient <thrift2_ip> <thrift2_port> 命令试试。

三、总结

1、在 /usr/hdp/2.6.4.0-91/hbase/include/thrift 目录下有两个文件,为 hbase1.thrifthbase2.thrift ,分别对应的thrift 1服务与thrift 2服务。本文采用 thrift 2 连接 HBase 数据库对表进行数据插入与读取操作。

2、使用 thrift --gen cpp hbase2.thrift 命令生成服务端相关代码。

3、在编写客户端文件时,通过 THBaseService.h 文件访问 HBase 服务端,使用 hbase2.thrift 文件内提供的方法对 HBase 数据库进行操作。

四、参考资料

我将这两天搜集的资料,觉得不错的列在下面,也方便继续深入的人查阅。

  • https://www.cnblogs.com/yhp-smarthome/p/8982758.html
  • https://www.cnblogs.com/zhaoxd07/p/5387215.html
  • https://blog.csdn.net/u013913435/article/details/77119647
  • 有些方法的描述: http://blog.chinaunix.net/uid-31429829-id-5785871.html?tdsourcetag=s_pctim_aiomsg
  • 根据这个实现:https://blog.csdn.net/yinzhiqing/article/details/51943370
  • https://blog.csdn.net/happyrabbit456/article/details/8116305
  • 看着不错,但没具体参照实现: https://blog.csdn.net/zhijiayang/article/details/46334707

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大数据实战演练 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、安装编译thrift
    • 1. 准备工作
      • 2. 下载thrift安装包
        • 3. 编译thrift
          • 4. 检查相关文件是否存在
          • 二、代码示例
            • 1. 开启HBase thrift2
              • 2. 生成c++相关文件
                • 3. 编写客户端代码
                  • 4. 生成可执行的文件HbaseClient
                    • 5. 创建HBase表
                      • 6. 运行客户端
                      • 三、总结
                      • 四、参考资料
                      相关产品与服务
                      TDSQL MySQL 版
                      TDSQL MySQL 版(TDSQL for MySQL)是腾讯打造的一款分布式数据库产品,具备强一致高可用、全球部署架构、分布式水平扩展、高性能、企业级安全等特性,同时提供智能 DBA、自动化运营、监控告警等配套设施,为客户提供完整的分布式数据库解决方案。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档