hbase/thrift/go连接失败

问题

在通过Go连接hbase的过程中, 发现 get操作可以查到数据, 但是scanner命令访问数据失败, 也没有报错, 就是单纯的查不到数据. 而且Python PHP都一切正常.

这里简单复述一下我出现问题的情况, 安装过程和网上大部分内容一致, 这里简单列一下, 只是为了查询问题时参考安装过程的差异:

# 安装hbase
wget -O /opt/hbase.tar.gz https://dlcdn.apache.org/hbase/2.4.11/hbase-2.4.11-bin.tar.gz
tar -xzf /opt/hbase.tar.gz -C /opt/
rm /opt/hbase.tar.gz
# 安装thrift
apt install -y libboost-dev  \libboost-test-dev  \libboost-program-options-dev  \libevent-dev  \automake  \libtool  \flex  \bison  \pkg-config  \g++  \libssl-dev \gcc  \autoconf \make \&& wget -O /opt/thrift.tar.gz https://dlcdn.apache.org/thrift/0.16.0/thrift-0.16.0.tar.gz \&& tar -xzf /opt/thrift.tar.gz -C /opt \&& rm /opt/thrift.tar.gz \&& cd /opt/thrift-0.16.0 \&& ./configure \&& make \&& make install
# 测试使用, 将hbase服务改为单机模式
cat > /opt/hbase-2.4.11/conf/hbase-site.xml <<- EOF
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration><!-- hbase存放数据目录 --><property><name>hbase.rootdir</name><value>file:///data/hbase</value></property><!-- ZooKeeper数据文件路径 --><property><name>hbase.zookeeper.property.dataDir</name><value>/data/zookeeper</value></property><property><name>hbase.unsafe.stream.capability.enforce</name><value>false</value></property>
</configuration>
EOF
# 启动hbase服务
/opt/hbase-2.4.11/bin/start-hbase.sh
# 启动htrift服务
/opt/hbase-2.4.11/bin/hbase-daemon.sh start thrift2 -p 9091# 生成go和python的thrift工具文件
wget -O ~/hbase_src.tar.gz https://dlcdn.apache.org/hbase/2.4.11/hbase-2.4.11-src.tar.gz
tar -xzf ~/hbase_src.tar.gz -C ~
cd ~/hbase-2.4.11/hbase-thrift/src/main/resources/org/apache/hadoop/hbase/thrift2
thrift --gen go hbase.thrift
thrift --gen py hbase.thrift

服务启动后, 使用GO进行查询(其中test表已经提前放入数据):

transport, err := thrift.NewTSocket(net.JoinHostPort("127.0.0.1", "9091"))
if err != nil {panic(err)
}
protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
client := hbase.NewTHBaseServiceClientFactory(transport, protocolFactory)
transport.Open()
scan := &hbase.TScan{}
ret, err := client.GetScannerResults(context.Background(), []byte("test"), scan, 100)
if err != nil {panic(err)
}
fmt.Println("scanner result")
fmt.Println(ret)

发现使用go查询不到数据???这个就奇怪了, 因此开始进行检查(简单复现一下问题查询步骤).

原因追溯

首先, 在使用GO查询之前已经使用hbase shell连接过了, 因此可以确定不是hbase启动失败的问题. 因此思考各种问题逐一排查.

端口未开启

使用命令telnet 127.0.0.1 9091进行验证, 端口没有问题, 可以排除.

是否仅Go有问题

使用python php进行连接并访问相同方法, 发现是有返回数据的, Python代码:

from thrift.transport import TSocket
from thrift.protocol import TBinaryProtocol
from thrift.transport import TTransport
from hbase import THBaseService
from hbase.ttypes import TScanif __name__ == '__main__':transport = TTransport.TBufferedTransport(TSocket.TSocket('127.0.0.1', 9091))protocol = TBinaryProtocol.TBinaryProtocolAccelerated(transport)client = THBaseService.Client(protocol)transport.open()# 使用 client 实例进行操作ret = client.getScannerResults(table="test",tscan=TScan(),numRows=100)print(ret)transport.close()

由此可以证明, thrift也没有问题, 一定是Go在连接的时候出了问题.

是否Go所有方法都有问题

尝试调用thrift其他方法, 判断是仅scanner方法有问题, 还是所有方法都有问题:

tGet := hbase.TGet{Row: []byte("row1"), // row1 数据是存在的
}
getRet, err := client.Get(context.Background(), []byte("test"), &tGet)
if err != nil {panic(err)
}
fmt.Println("get result")
fmt.Println(getRet)

查询后发现, Get方法是可以获取到数据的, 那么, 就是说仅GoGetScannerResults方法是有问题的???

当问题追溯到这里的时候, 我已经有些懵了, 尝试这谷歌查找原因, 各种关键词都试过了, 没有找到想要的答案(这也是为什么我要把这个错记下来, 因为没查到啊)

抓包比较差异

找了半天没有找到问题, 既然Python可以查到数据 而Go查不到, 那么, 就可以尝试抓包比较两者差异了嘛.

依然使用上面的GetScannerResults, 分别对pythongo进行抓包分析, 通过命令tmpdump port 9091 -w thrift.cap:

image-20220417134443514

image-20220417134458800

可以看到, 其中的thrift请求也能够被wireshark识别了, 那就太好了, 不用比较二进制了, 来看一下两个请求的区别:

Python请求如下:

image-20220417134751836

Go请求如下:

image-20220417134903197

其中, 有一个字段两个是明显不一样的, 我很贴心的用红框圈出来了, 那么, 问题来了, 这个字段是什么呢? 我把上面的hbase.thrift文件中的一部分拿出来, 就很明显了:

/*** Any timestamps in the columns are ignored but the colFamTimeRangeMap included, use timeRange to select by timestamp.* Max versions defaults to 1.*/
struct TScan {1: optional binary startRow,2: optional binary stopRow,3: optional list<TColumn> columns4: optional i32 caching,5: optional i32 maxVersions=1,6: optional TTimeRange timeRange,7: optional binary filterString,8: optional i32 batchSize,9: optional map<binary, binary> attributes10: optional TAuthorization authorizations11: optional bool reversed12: optional bool cacheBlocks13: optional map<binary,TTimeRange> colFamTimeRangeMap14: optional TReadType readType15: optional i32 limit16: optional TConsistency consistency17: optional i32 targetReplicaId18: optional binary filterBytes}service THBaseService {/*** Get results for the provided TScan object.* This helper function opens a scanner, get the results and close the scanner.** @return between zero and numRows TResults*/list<TResult> getScannerResults(/** the table to get the Scanner for */1: required binary table,/** the scan object to get a Scanner for */2: required TScan tscan,/** number of rows to return */3: i32 numRows = 1) throws (1: TIOError io)
}

虽然我没用过thrift, 但是看着这个数据包, 在看看这个数据结构的定义, 很明显Field Id就是定义文件中前面的数字啊.

很好, 这就可以定位到不用的字段为: maxVersion, 而这个字段指定了返回的版本数量, 0个版本自然就没有数据咯.

解决

既然查询到时因为maxVersion字段不同而导致的问题, 那么在查询的时候手动指定即可. 修改代码后重试:

scan := &hbase.TScan{maxVersion: 1
}
ret, err := client.GetScannerResults(context.Background(), []byte("test"), scan, 100)
if err != nil {panic(err)
}
fmt.Println("scanner result")
fmt.Println(ret)

OK, 现在有数据了, 查半天没想到是这个问题. 至此, 问题解决…

我是不懂为什么不同语言访问还有这种差异? 是因为字段的默认值不同? 搞不懂.

再顺便提一句, 难道大家都没有碰到这个问题么? 我搁网上查了半天, 愣是没找到一个沾边的…若你也碰到了这个问题, 希望能够帮到你

原文地址: https://hujingnb.com/archives/767

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/508351.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常用搜索引擎及语法

在平常需要进行搜索的时候是不是只知道Google Baidu ?? 他们其实是全文搜索引擎, 还有一些特定领域的搜索引擎. 而且, 搜索时可以添加特定语法, 让你的搜索事半功倍. 本文整理各种场景下使用的搜索引擎, 以及各个搜索引擎支持的语法, 不定期进行更新. 如果你知道其他搜索引…

自旋锁与互斥锁

前言 在编程中经常需要使用到互斥. 互斥就是, 这个事情只能有一个人干, 我正在做着的时候, 别人要想做这件事就得等我做完了. 互斥的实现是通过锁的机制, 也就是我把这块锁上了, 别人就进不来了, 等我做完再把锁释放掉. 但是, 前辈们已经证明了, 要想单纯的在软件层面上实现…

printf缓冲区踩坑

问题 碰到了这样一段代码(经过简化的): #include "stdio.h" #include "unistd.h" #include "sys/wait.h"int main(){fork();printf("1\n");fork();printf("1\n");wait(NULL);return 0; }这里我们简单算一下, 结果会打印几…

进程切换时是如何保存上下文的

前言 当前操作系统大部分采用分时的进程调度, 既每个进程运行一小段时间, 然后切换到下一个进程运行, 依次往复. 当进程运行的时候是独占CPU的, 此时操作系统是无法强行介入的, 为了将执行权让出来, 就需要硬件的配合了. 硬件每个一个时钟周期(比如10ms), 就会产生一个时钟中…

GO/testing包

前言 之前在写GO单元测试的时候, 使用了这个结构testing.T. 进来无事翻了翻, 发现testing包中还有一些其他的结构体, 想来是不同用处. 没想到GO的testing包竟然默默做了这么多支持, 之前竟然不知道. 在testing包中包含一下结构体: testing.T: 这就是我们平常使用的单元测试t…

CPU的分支预测

前言 最近在进行性能调优的时候, 碰到了这样的一段代码(为了展示问题而简化的代码): <?php // 第一次运行 $start microtime(true); for ($i 0; $i < 100; $i) {for ($j 0; $j <1000; $j) {for ($k 0;$k < 10000; $k) {}} } $end microtime(true); echo fi…

Golang Context 简介

前言 在写Golang程序调用各种第三方库的时候, 经常会传一个叫做Context的参数. 之前基本上见到接Context, 根本不管是干什么用的, 直接无脑context.Background(). 但是, 传着传着就不免发生一些小疑问, 这个参数到底是干什么用的呢? 这么多库都在使用, 至少说明其是Golang中…

PHP获取Opcode及C源码

是什么 在开始之前, 必须要先介绍一下Opcode是什么. 众所周知, Java在执行的时候, 会将.java后缀的文件预先编译为.class字节码文件, JVM加载字节码文件进行解释执行. 而字节码文件存在的意义, 就是为了加速执行. 那么PHP的Opcode与之类似, 也是从.php文件到执行的过程中, 所…

PHP require/include 区别

前言 在PHP中, 载入文件可以选择使用require, 也可以使用include, 那么那他们有什么区别呢? 看了网上的一些文章, 说他们使用场景不同, require一般在文件开头引入文件, include一般在函数中动态引入文件. 但是我觉得并不是这么简单, require是作为语言结构(关键字)出现的, …

RESTful API规范

前言 我现在工作的公司是在毕业前实习的公司, 实习结束后直接转正, 因此也是我任职过的唯一一家公司. 在日常工作进行 HTTP 接口的开发时, 发现了一个疑惑, 只用到了POST和GET请求, 但我们知道 HTTP还有PUT/DELETE等等, 为什么不用呢? 并且, 接口的响应码也只有200, 接口是…

Golang 接口原理

问题 小提示, 若想直接查看原理, 可从接口原理开始查看. 有这样一段GO代码: func main() {var obj interface{}fmt.Printf("obj nil. %b\n", obj nil)type st struct{}var s *stobj sfmt.Printf("s nil. %b\n", s nil)fmt.Printf("obj nil. …

Docker kill 1无效

前言 我们在平常强制停用一个进程的时候, 会选择什么命令? 一般在测试使, 不考虑程序突然中断带来的影响, 直接使用kill -9 pid强制停止就行. 但是, 就在刚刚, 我启动了一个docker容器, 进入容器后执行命令kill -9 1没有任何效果??? 啊这, 为什么呀? 尝试 为了解释这个…

容器内存相关知识

这篇文章是我研究容器内存整理出的相关内容. 前后内容并没有上下文关系, 每个知识点都可以单独查看. 内存控制 使用这样的命令启动一个容器docker run -d -m 300M xxx. 可以限制容器使用的内存最大为300M. 那么docker是如何实现容器的内存限制呢? 其实是操作系统已经做好了…

三星识别文字_比亚迪电子助力三星Galaxy Note 10系列霸气首发!

三星有子初长成气宇轩昂 秀美俊逸减之一分则嫌柔增之一分则嫌赘2019年8月7日于纽约巴克莱发布Galaxy Note 10系列用简约 重构美三星Galaxy Note 10与Galaxy Note 10分别搭载了6.3英寸和6.8英寸的超感官全视曲面屏&#xff0c;均采用单摄挖孔屏&#xff0c;开孔位于屏幕正上方。…

lisp 设计盘形齿轮铣刀_机械设计基础——周转轮系传动比的计算

点击上方蓝色字体&#xff0c;关注我们15(视频来源于网络&#xff0c;仅供学习交流&#xff0c;侵权请联系删除)机械计重点学习指导机械原理全书重点提要轴的结构改错机械设计作业集01机械设计作业集02机械设计作业集答案机械原理作业集机械原理作业集答案轴的强度计算院校推荐…

b+树阶怎么确定_B站公布年度弹幕,这个排名我不太服气

也忘记了是从什么时候开始&#xff0c;B站开始公布自己的年度弹幕了&#xff0c;今年的年度弹幕排名前五的分别是&#xff1a;爷青回、武汉加油、有内味了、双厨狂喜、禁止套娃。话说今年真的是不容易啊&#xff0c;过年那段时间以及上半年不会忘记那一幕幕感人深邃的瞬间&…

css打印适应纸张_从生态平衡到打印机故障分析

生态平衡(ecological equilibrium)是指在一定时间内生态系统中的生物和环境之间、生物各个种群之间&#xff0c;通过能量流动、物质循环和信息传递&#xff0c;使它们相互之间达到高度适应、协调和统一的状态。也就是说当生态系统处于平衡状态时&#xff0c;系统内各组成成分之…

html5调用系统声音1s响一次_20款奔驰GLC260提车改柏林之声音响,音乐诉请,为爱发声!...

奔驰GLC车型在2020上半年可谓是风生水起&#xff0c;尤其是2020年1-5月份的豪华品牌SUV排名中&#xff0c;奔驰GLC车型以58982的销售量遥遥领先&#xff0c;同比增长了2%&#xff0c;奔驰GLC5月销量高达15275辆&#xff0c;再次打败老对手奥迪Q5L&#xff0c;夺得豪华SUV销量冠…

js排序的时间复杂度_冒泡排序最好时间复杂度为什么是O

展开全部冒泡排序的基本思想是&#xff0c;对相邻的元素进行两两比较&#xff0c;顺序相反则进行交换&#xff0c;这样&#xff0c;每一趟会e68a8462616964757a686964616f31333433616161将最小或最大的元素“浮”到顶端&#xff0c;最终达到完全有序代码实现在冒泡排序的过程中…

kotlin将对象转换为map_将网站转换为Photoshop文档

WebToLayers是一款能够帮助大家将网页转换成图像格式的软件&#xff0c;能够Web页面转换成PNG&#xff0c;JPG以及PSD格式的图片。当网页转换为PSD的时候&#xff0c;网页的各个要素都会自动转换为相应的图层&#xff0c;使得大家能够对PSD格式的网页进行设计与管理。WebToLaye…