HBase & thrift & C++编程

1. 前言

本文目的是介绍使用C++如何操作HBase。从HBase 0.94开始,HBase新增thrift2,本文只介绍和讨论thrift2相关的。hbase-1.1.2使用的thrift估计是thrift-0.9.0版本。

2. 启动和停止thrift2

2.1. 启动thrift2

登录HBase master机器,执行以下命令启动thrift2:hbase-daemon.sh start thrift2。

thrift默认的监听端口是9090,可以通过参数“-p”指定其它端口。默认使用的Server是TThreadPoolServer。默认使用的Protocol是TBinaryProtocol。

注意客户端使用的Protocol和Transport和服务端的要保持一致,否则客户端在调用时,可能遇到“EAGAIN (timed out)”等错误。

2.2. 停止thrift2

hbase-daemon.sh stop thrift2

2.3. 启动参数

使用“hbase-daemon.sh start thrift2”时,还可以带以下参数:

参数名

是否默认

参数说明

-h, --help

显示帮助信息

-b, --bind

绑定指定地址,但不支持TNonblockingServer和THsHaServer,两者总是使用“0.0.0.0”

-p, --port

9090

绑室指定端口,默认为9090

-f, --framed

使用TFramedTransport

-c, --compact

使用TCompactProtocol,默认是TBinaryProtocol

-threadpool

使用TThreadPoolServer,为默认Server

-nonblocking

使用实现了FramedTransport的TNonblockingServer

-hsha

使用实现了FramedTransport的THsHaServer

客户端和hbase thrift2的Transport和Protocol需保持一致,比如客户端为FramedTransport,则也需以“-f”启动hbase thrift2。

否则客户端在调用时,可能会遇到“EAGAIN (timed out)”等错误。

启动参数信息来源于官网的页面:

https://hbase.apache.org/devapidocs/org/apache/hadoop/hbase/thrift2/package-summary.html

以上参数不是给hbase-daemon.sh使用,而是被hbase thrift2使用,可以浏览相关源代码了解细节:

hbase-thrift\src\main\java\org\apache\hadoop\hbase\thrift2\ThriftServer.java

hbase-thrift\src\main\java\org\apache\hadoop\hbase\thrift2\ThriftHBaseServiceHandler.java

? 启动示例:

hbase-daemon.sh start thrift2 --framed -nonblocking

3. hbase.thrift

hbaser.thrift文件在hbase源代码包(以hbase-1.1.2为例)中的位置:

hbase-thrift\src\main\resources\org\apache\hadoop\hbase\thrift2\hbase.thrift

3.1. 编译hbase.thrift

保持机器上已安装好thrift(经测试hbase-1.1.2和thrift-0.9.0兼容),然后使用下列命令编译:thrift --gen cpp -out . hbase.thrift,编译成功后,会在“-out”指定的目录下生成以下五个文件:

THBaseService.h

THBaseService.cpp

hbase_types.h

hbase_types.cpp

hbase_constants.h

hbase_constants.cpp

其中供客户端使用的是位于文件THBaseService.h中的类THBaseServiceClient。

4. thrift_helper.h

为了简化C++客户端的编程,可以使用thrift_helper.h:

https://github.com/eyjian/mooon/blob/master/common_library/include/mooon/net/thrift_helper.h,它可以帮助简化对HBase thrift2的调用:

// thrift客户端辅助类
//
// 使用示例:
// mooon::net::CThriftClientHelper client(rpc_server_ip, rpc_server_port);
// try
// {
//     client.connect();
//     client->foo();
// }
// catch (apache::thrift::transport::TTransportException& ex)
// {
//     MYLOG_ERROR("thrift exception: (%d)%s\n", ex.getType(), ex.what());
// }
// catch (apache::thrift::transport::TApplicationException& ex)
// {
//     MYLOG_ERROR("thrift exception: %s\n", ex.what());
// }
// catch (apache::thrift::TException& ex)
// {
//     MYLOG_ERROR("thrift exception: %s\n", ex.what());
// }
// Transport除默认的TFramedTransport (TBufferTransports.h),还可选择:
// TBufferedTransport (TBufferTransports.h)
// THttpTransport
// TZlibTransport
// TFDTransport (TSimpleFileTransport)
//
// Protocol除默认的apache::thrift::protocol::TBinaryProtocol,还可选择:
// TCompactProtocol
// TJSONProtocol
// TDebugProtocol
template
class Protocol=apache::thrift::protocol::TBinaryProtocol,
class Transport=apache::thrift::transport::TFramedTransport>
class CThriftClientHelper

5. 示例代码

// HBase thrift2 C++编程示例
#include "THBaseService.h"
#include  // PRIu64
#include
#include
#include
// 请注意客户端使用的thrift的Transport和Protocol要和hbase thrift2服务端保持一致,
// 否则调用时,可能总是报超时,或其它错误!!!
//
// 运行之前,请通过HBase shell创建好表:create 'test','cf1','cf2'
// 或指定版本数:create 'test',{NAME=>'cf1',VERSIONS=>2},{NAME=>'cf2',VERSIONS=>3}
// 删除表,按顺序执行以下两条HBase shell命令:
// disable 'test'
// drop 'test'
STRING_ARG_DEFINE(hbase_ip, "192.168.0.1", "hbase thrift ip");
INTEGER_ARG_DEFINE(uint16_t, hbase_port, 9090, 1000, 50000, "hbase thrift port");
int main(int argc, char* argv[])
{
std::string errmsg;
if (!mooon::utils::parse_arguments(argc, argv, &errmsg))
{
fprintf(stderr, "parameter error: %s\n", errmsg.c_str());
exit(1);
}
using namespace apache;
using namespace apache::hadoop;
std::string hbase_ip = mooon::argument::hbase_ip->value();
uint16_t hbase_port = mooon::argument::hbase_port->value();
mooon::net::CThriftClientHelper hbase_client(hbase_ip, hbase_port);
try
{
hbase_client.connect(); // 连接hbase thrift2 server
fprintf(stdout, "connect %s:%d ok\n", hbase_ip.c_str(), hbase_port);
std::string tablename = "test";     // 表名,确保运行之前已创建好
std::string rowkey = "row1";        // 行Key
std::string family = "cf1";         // 例族名
std::string columnname = "f1";      // 例名
std::string columnvalue = "value1"; // 例值
// 插入参数设置
std::vector columns_value(1);
columns_value[0].__set_family(family);
columns_value[0].__set_qualifier(columnname);
columns_value[0].__set_value(columnvalue);
hbase::thrift2::TPut put;
put.__set_row(rowkey);
put.__set_columnValues(columns_value);
hbase_client->put(tablename, put); // 插入,出错抛异常hbase::thrift2::TIOError
// 查询参数设置
hbase::thrift2::TGet input;
input.__set_row(rowkey);
hbase::thrift2::TResult result; // 查询结果存放在这里
hbase_client->get(result, tablename, input); // 查询,出错抛异常hbase::thrift2::TIOError
// 显示查询结果
for (int i=0; i
{
const hbase::thrift2::TColumnValue& column_value_ref = result.columnValues[i];
fprintf(stdout, "family[%s]/qualifier[%s]/timestamp[%"PRIu64"]: %s\n", column_value_ref.family.c_str(),
column_value_ref.qualifier.c_str(),
column_value_ref.timestamp,
column_value_ref.value.c_str());
}
}
catch (hbase::thrift2::TIOError& ex)
{
fprintf(stderr, "IOError: %s\n", ex.what());
}
catch (apache::thrift::transport::TTransportException& ex)
{
// 如果和服务端的Transport和Protocol不同,这里的错误是“EAGAIN (timed out)”
fprintf(stderr, "(%d)%s\n", ex.getType(), ex.what());
}
catch (apache::thrift::TApplicationException& ex)
{
fprintf(stderr, "%s\n", ex.what());
}
catch (thrift::TException& ex)
{
fprintf(stderr, "%s\n", ex.what());
}
return 0;
}

如果thrift客户端报如下错误,有可能是因为一次写入的数据太多,导致包过大:

Thrift: Fri Apr 22 17:30:41 2016 TSocket::write_partial() send() Connection reset by peer

Thrift: Fri Apr 22 17:30:41 2016 TSocket::write_partial() send() Connection reset by peer

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏xingoo, 一个梦想做发明家的程序员

linux虚拟机与winodows共享文件夹----linux安装VMware tools

虚拟机里面想要获取原来本机 系统的文件,十分麻烦。为了实现原系统与虚拟机的共享文件夹,可以通过安装vmware tools达到共享目的。 1 安装vmware ...

2419
来自专栏cs

网络测试与分析工具简介

<h2>主要是几个dos命令,直接上图和网上已有的知识</h2> <ol> <li>ipconfig<b>----查看和设置网络配置</b></li> <...

3124
来自专栏埋名

CentOS7安装维护Gitlab

下面是官网复制过来的官方安装方法,最简单的安装,在我大天朝,只能望天兴叹,你可翻墙安装或者略过这里,看下面的。

5073
来自专栏云计算教程系列

如何使用Apache驱动Django

Django是一个功能强大的Web框架,可以帮助您快速启动Python应用程序或网站。Django包含一个简化的开发服务器,用于在本地测试您的代码。但是其也需要...

2985
来自专栏小樱的经验随笔

kali 2018.1安装教程

00x01 摘要 Kali-linux系统,渗透测试人员的利器,其官网自称 OurMost Advanced Penetration Testing Distr...

4026
来自专栏刘君君

Spring Boot配置属性

3766
来自专栏云计算教程系列

如何在Ubuntu 16.04上使用Apache和mod_wsgi为Django应用程序提供服务

Django是一个功能强大的Web框架,可以帮助您快速启动Python应用程序或网站。Django包含一个简化的开发服务器,用于在本地测试您的代码,但是对于任何...

1320
来自专栏CaiRui

memcached服务

介绍 它是一套数据缓存系统或软件 用于动态应用系统中缓存数据库的数据,减少数据库的访问压力,达到提升性能的效果,实际应用环境中多用于数据库的cache的应用。它...

3768
来自专栏电光石火

eclipse配置tomcat运行时访问路径不要项目名称

1:双击打开tomcat 2:选择Modules,选择你要修改的项目 ? 3:点击Edit,把path修改成空或者你自己想要的路径即可! ?

3096
来自专栏丑胖侠

Spring boot 数据源未配置异常

问题 在使Springboot自动生成的项目框架时如果选择了数据源,比如选择了mysql,生成项目之后,启动会报一下异常: Description: Cann...

3268

扫码关注云+社区

领取腾讯云代金券