Openresty/Lua + Thrift + HBase
来源:互联网 发布:网络机顶盒刷机通用版 编辑:程序博客网 时间:2024/06/01 10:25
1. 问题
在Openresty环境下(也就是lua语言下),如何访问HBase?Lua不方便调用HBase的原生API(Java),所以只能通过别的方式,例如:
- Rest
- Thrift
2. Thrift是什么
简单来说,Thrift是一种SOA(Service Oriented Architecture)的实现方式,和WSDL+SOAP那一套类似。过程都是这样的:
- 以一种接口语言定义接口(对于WSDL+SOAP是.wsdl文件;对于Thrift是.thrift文件);
- 使用一个编译器,把接口文件(.wsdl或者.thrift)转化为代码(客户端类和服务端虚基类/接口);
- 继承服务端虚基类/接口,实现服务端逻辑;并部署服务;
- 基于客户端类,通过少量的开发即可实现客户端,与服务端通信。
Thrift或者WSDL+SOAP框架帮助程序员实现远程方法调用,在整个过程中,程序员不用考虑参数的序列化、网络传输、返回数据的反序列化,甚至包括安全、事务等方面的工作。
3. 环境
- CentOS 7
- Luajit:为了很好的和openresty结合,我们使用openresty 1.9.15.1包自带的luajit;它和lua 5.1兼容;
- Thrift 0.9.2:目前最新版是0.9.3,但是Thrift 0.9.3需要lua 5.2及以上版本,所以我们使用和lua 5.1兼容的Thrift 0.9.2。这为我们带来很多麻烦,因为Thrift 0.9.2有一些bug,见后文Thrift安装部分;
- HBase 1.2.2:它里面有两个Thrift Server:thrift基于HBase的老API;thrift2基于HBase的新API;我们使用后者。
4. HBase安装与配置
HBase的安装与配置涉及到Hadoop hdfs和zookeeper,这里略去其过程。HBase服务成功启动后,启动Thrift服务:
# /usr/local/hbase-1.2.2/bin/hbase-daemon.sh start thrift2 -p 9090 --infoport 9095
5. Openresty安装
目前我们只需要使用luajit,但为了后续与openresty兼容,干脆这里把openresty安装了,后面实验直接使用它自带的luajit。假定已经安装了PCRE,OpenSSL等依赖:
# cd /tmp/# wget https://openresty.org/download/openresty-1.9.15.1.tar.gz# tar zxvf openresty-1.9.15.1.tar.gz# cd openresty-1.9.15.1/# ./configure --prefix=/usr/local/openresty-1.9.15.1 --without-lua51 --with-luajit# gmake# gmake install# ln -s /usr/local/openresty-1.9.15.1/luajit/lib/libluajit-5.1.so /usr/lib64/libluajit-5.1.so# ln -s /usr/local/openresty-1.9.15.1/luajit/lib/libluajit-5.1.so.2 /usr/lib64/libluajit-5.1.so.2现在,我们就有了luajit:/usr/local/openresty-1.9.15.1/luajit/
6. 安装Thrift
6.1 安装依赖
# yum install readline.x86_64 install readline-devel.x86_64# yum install libtool.x86_64# yum install boost.x86_64 boost-devel.x86_64# yum install byacc.x86_64# yum install flex.x86_64 flex-devel.x86_64 # yum install openssl.x86_64 openssl-devel.x86_64
6.2 编译安装Thrift
# cd /tmp/# git clone https://github.com/apache/thrift# cd thrift/# git branch -a# git checkout -b 0.9.2 origin/0.9.2 <-- 切换到0.9.2版本# ./bootstrap.sh# ./configure --prefix=/usr/local/thrift-0.9.2 LUA=/usr/local/openresty-1.9.15.1/luajit/bin/luajit LUA_INCLUDE=-I/usr/local/openresty-1.9.15.1/luajit/include/luajit-2.1 LUA_LIB=-lluajit-5.1
修改bug1:
# vim lib/lua/src/luabpack.c106c106< size_t len = lua_rawlen(L, 2);---> size_t len = lua_objlen(L, 2);
修改bug2:
# vim lib/lua/Makefile385a386,387> LUA_INCLUDE=-I/usr/local/openresty-1.9.15.1/luajit/include/luajit-2.1> LUA_LIB=-lluajit-5.1516,517c518,519< libluasocket_la_CPPFLAGS = $(AM_CPPFLAGS) -I/usr/include/lua5.2 -DLUA_COMPAT_MODULE< libluasocket_la_LDFLAGS = $(AM_LDFLAGS) -llua5.2 -lm---> libluasocket_la_CPPFLAGS = $(AM_CPPFLAGS) $(LUA_INCLUDE) -DLUA_COMPAT_MODULE> libluasocket_la_LDFLAGS = $(AM_LDFLAGS) $(LUA_LIB) -lm519,520c521,522< libluabpack_la_CPPFLAGS = $(AM_CPPFLAGS) -I/usr/include/lua5.2 -DLUA_COMPAT_MODULE< libluabpack_la_LDFLAGS = $(AM_LDFLAGS) -llua5.2 -lm---> libluabpack_la_CPPFLAGS = $(AM_CPPFLAGS) $(LUA_INCLUDE) -DLUA_COMPAT_MODULE> libluabpack_la_LDFLAGS = $(AM_LDFLAGS) $(LUA_LIB) -lm523,524c525,526< libluabitwise_la_CPPFLAGS = $(AM_CPPFLAGS) -I/usr/include/lua5.2 -DLUA_COMPAT_MODULE< libluabitwise_la_LDFLAGS = $(AM_LDFLAGS) -llua5.2 -lm---> libluabitwise_la_CPPFLAGS = $(AM_CPPFLAGS) $(LUA_INCLUDE) -DLUA_COMPAT_MODULE> libluabitwise_la_LDFLAGS = $(AM_LDFLAGS) $(LUA_LIB) -lm529,530c531,532< liblualongnumber_la_CPPFLAGS = $(AM_CPPFLAGS) -I/usr/include/lua5.2 -DLUA_COMPAT_MODULE< liblualongnumber_la_LDFLAGS = $(AM_LDFLAGS) -llua5.2 -lm---> liblualongnumber_la_CPPFLAGS = $(AM_CPPFLAGS) $(LUA_INCLUDE) -DLUA_COMPAT_MODULE> liblualongnumber_la_LDFLAGS = $(AM_LDFLAGS) $(LUA_LIB) -lm
修改bug3:
# vim lib/lua/Makefile508a509> liblualongnumber.la \510,511c511< libluabitwise.la \< liblualongnumber.la---> libluabitwise.la
好,现在开始make并make install。若make因缺失依赖而失败,需要make clean,重新configure,重新fix上面的bug,然后重试make。
# make# make install
另外,make install不会拷贝lua库,所以需要手动拷贝
# mkdir /usr/local/thrift-0.9.2/lualib# cp lib/lua/*.lua /usr/local/thrift-0.9.2/lualib/
修改bug4:错误 Thrift.lua:43: malformed number near '0.9.2'
# vim /usr/local/thrift-0.9.2/lualib/Thrift.lua43c43< version = 0.9.2---> --version = 0.9.2
修改bug5:创建TBufferedTransport实例时,误创建为的TTransportBase实例。
# vim /usr/local/thrift-0.9.2/lualib/TBufferedTransport.lua40c40< return TTransportBase:new(obj)---> return TTransportBase.new(self,obj)
Thrift安装完毕!
7. 访问HBase
7.1 找到.thrift文件
下载HBase 1.2.2源代码,里面包含两个.thrift文件。它们是接口定义文件,类似于WSDL+SOAP里面的.wsdl文件:
# find . -name "*.thrift"./hbase-thrift/src/main/resources/org/apache/hadoop/hbase/thrift2/hbase.thrift./hbase-thrift/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift我们只需要上面那个,它是thrift2的接口定义。
7.2 编译.thrift文件生成lua文件
# cd /home# mkdir test# cd test/# cp /home/hbase-1.2.2/hbase-thrift/src/main/resources/org/apache/hadoop/hbase/thrift2/hbase.thrift .# /usr/local/thrift-0.9.2/bin/thrift -r --gen lua hbase.thrift# lsgen-lua hbase.thrift# ll gen-lua/ <--生成的目录和文件total 120-rw-r--r--. 1 root root 136 Aug 30 10:04 hbase_constants.lua-rw-r--r--. 1 root root 74532 Aug 30 10:04 hbase_THBaseService.lua-rw-r--r--. 1 root root 38447 Aug 30 10:04 hbase_ttypes.lua
修改bug6: 生成代码错误
# vim gen-lua/hbase_ttypes.lua508c508< oprot:writeListBegin(TType.STRUCT, string.len(self.columns))---> oprot:writeListBegin(TType.STRUCT, #self.columns)<strong></strong>
7.3 使用生成的lua文件访问HBase
# mkdir mycode# vim mycode/client.lua
#!/usr/local/openresty-1.9.15.1/luajit/bin/luajitrequire('TSocket')require('TBufferedTransport')require('TFramedTransport')--require('THttpTransport')--require('TCompactProtocol')--require('TJsonProtocol')require('TBinaryProtocol')require('liblualongnumber')require('hbase_THBaseService')local client = nilfunction teardown() if client then -- close the connection client:close() endendfunction parseArgs(rawArgs) local opt = { protocol='binary', transport='buffered', port='9090', } for i, str in pairs(rawArgs) do if i > 0 then k, v = string.match(str, '--(%w+)=(%w+)') assert(opt[k] ~= nil, 'Unknown argument') opt[k] = v end end return optendfunction assertEqual(val1, val2, msg) assert(val1 == val2, msg)endfunction testBasicClient(rawArgs) local opt = parseArgs(rawArgs) local socket = TSocket:new{ port = tonumber(opt.port) } assert(socket, 'Failed to create client socket') socket:setTimeout(5000) local transports = { buffered = TBufferedTransport, framed = TFramedTransport, http = THttpTransport, } assert(transports[opt.transport] ~= nil) local transport = transports[opt.transport]:new{ trans = socket, isServer = false } local protocols = { binary = TBinaryProtocol, compact = TCompactProtocol, json = TJSONProtocol, } assert(protocols[opt.protocol] ~= nil) local protocol = protocols[opt.protocol]:new{ trans = transport } assert(protocol, 'Failed to create binary protocol') client = THBaseServiceClient:new{ protocol = protocol } assert(client, 'Failed to create client') -- Open the transport local status, _ = pcall(transport.open, transport) assert(status, 'Failed to connect to server') --1. check if a row exists local tget = TGet:new{ row="UUUU1234_bucket1" } local ok,ret = pcall(client.exists, client, "bucket", tget) if not ok or not ret then print("client:exists failed") else print("client:exists succeeded:") print("\t", ret) end --2. get a row local ok,ret = pcall(client.get, client, "bucket", tget) if not ok or not ret then print("client:get failed") else print("client:get succeeded:") local row=ret.row for i,v in pairs(ret.columnValues) do print("\t",row, v.family..":"..v.qualifier, v.value) end endendtestBasicClient(arg)teardown()
我是参照thrit源代码中test_basic_client.lua搞通的,前文提到的bug5也是在这个测试中发现。当然,HBase里的数据是我通过hbase shell手动插入的,这里只测试它是否存在,并get出来。
7.4 测试
为了方便运行,我写了个脚本:
# vim client.sh
#!/bin/bashTEST_HOME=/home/testTHRIFT_HOME=/usr/local/thrift-0.9.2LUA_HOME=/usr/local/openresty-1.9.15.1/luajitrm -fr gen-lua$THRIFT_HOME/bin/thrift -r --gen lua hbase.thriftexport LUA_PATH="$THRIFT_HOME/lualib/?.lua;$TEST_HOME/gen-lua/?.lua;$TEST_HOME/mycode/?.lua;;"export LUA_CPATH="$THRIFT_HOME/lib/?.so;;"$LUA_HOME/bin/luajit mycode/client.lua
运行结果:
# ./client.shclient:exists succeeded: trueclient:get succeeded: UUUU1234_bucket1 exattrs:content movies UUUU1234_bucket1 info:ctime Thu, 11 Aug 2016 02:14:45 +0000 UUUU1234_bucket1 info:mtime Thu, 11 Aug 2016 02:14:45 +0000 UUUU1234_bucket1 quota:enabled yes UUUU1234_bucket1 quota:objects 1024 UUUU1234_bucket1 quota:size_mb 1024000 UUUU1234_bucket1 stats:mb_rounded 0 UUUU1234_bucket1 stats:objects 0 UUUU1234_bucket1 stats:size_bytes 0 UUUU1234_bucket1 ver:tag BBBB1234 UUUU1234_bucket1 ver:version 0
8. 下一步
研究HBase Thrift API支持的接口(是否比REST丰富);
测试Thrift的性能;
0 0
- Openresty/Lua + Thrift + HBase
- HBase Thrift
- openresty+lua+module
- openresty+lua+module(2)
- openresty+lua+module(3)
- Deploy openresty + lua + zabbix
- 安装openresty+redis+lua
- 看看 Nginx + Lua (OpenResty)
- OpenResty+lua的方案
- lua之安装openresty
- Openresty (nginx + lua)
- Nginx+Lua(OpenResty) HelloWorld
- OpenResty(Nginx+Lua)
- nginx+lua+redis(openresty)配置
- openresty 限流 (redis+lua) 备忘
- lua + openresty web API 框架
- 安装openresty和lua记录
- openresty 安装nginx和lua
- 计数排序、桶排序和基数排序
- 后台的token、sessionId、RSA加密登录认证与安全解决方案
- springMvc+mybatis项目junit测试mybatis sql语句遇到的错误class not found:com.mysql.jdbc.Driver
- 登录注册验证码 js
- 任重道远——记2016暑假训练
- Openresty/Lua + Thrift + HBase
- android shape的使用
- 【OpenCV入门教程之十二】OpenCV边缘检测:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑
- ajax的同步与异步
- Unity 折叠树 EditorGUI.Foldout
- bzoj 4551: [Tjoi2016&Heoi2016]树 并查集
- VS2015添加Command Prompt 到工具菜单项
- Swap Nodes in Pairs -- leetcode
- CSS实现单行、多行溢出省略号