项目要求实现php读写hbase,调查发现中间件为thrift,参考了文章http://www.cnblogs.com/scotoma/archive/2013/05/16/3081236.html,老实讲帮助很大,总算按时完成了这些任务。
本地安装了php和hbase,网上很多教程安装thrift,安装后将thrift目录下./lib/php目录复制到web目录下,我的web目录是/usr/local/apache2/htdocs,接着生成thrift和hbase的接口文件,这里产生了很大的误区,开始参考以为Hbase.thrift是通过命令生成的文件,走了很多弯路。后面其实是--gen命令利用Hbase.thrift生成目录文件,具体可以参考到官方网站上https://thrift.apache.org/tutorial/php,这也给我提了很大的醒,还是要多关注官方网站的写法。这次虚拟机是直接拷贝的别人,里面没有Hbase.thrift文件,思考之后因为hbase安装使用的是二进制安装,最后在hbase源码里找到了Hbase.thrift文件。
thrift -r --gen php Hbase.thrift
生成的Hbase目录文件里会有Hbase.php和Types.php文件,后面会用到。
查看都hbase启动成功,便开始了代码测试,路径都要每一个对准,检查每一个class文件是否对应成功。
<?php
use Thrift\Transport\TSocket;
use Thrift\Transport\TSocketPool;
use Thrift\Transport\TFramedTransport;
use Thrift\Transport\TBufferedTransport;
use Thrift\Protocol\TBinaryProtocol;
use HBase\HBaseClient;
ini_set('display_errors', E_ALL);
$GLOBALS['THRIFT_ROOT'] = './php/src/Thrift';
require_once( $GLOBALS['THRIFT_ROOT'] . '/Thrift.php' );
require_once( $GLOBALS['THRIFT_ROOT'] . '/transport/TSocket.php' );
require_once( $GLOBALS['THRIFT_ROOT'] . '/transport/TTransport.php' );
require_once( $GLOBALS['THRIFT_ROOT'] . '/transport/TBufferedTransport.php' );
require_once( $GLOBALS['THRIFT_ROOT'] . '/protocol/TProtocol.php' );
require_once( $GLOBALS['THRIFT_ROOT'] . '/protocol/TBinaryProtocol.php' );
//require_once( $GLOBALS['THRIFT_ROOT'] . '/packages/Hbase/Hbase.php' );
require_once( $GLOBALS['THRIFT_ROOT'] . '/Type/TMessageType.php' );
require_once( $GLOBALS['THRIFT_ROOT'] . '/Factory/TStringFuncFactory.php' );
require_once( $GLOBALS['THRIFT_ROOT'] . '/StringFunc/TStringFunc.php' );
require_once( $GLOBALS['THRIFT_ROOT'] . '/StringFunc/Core.php' );
require_once( $GLOBALS['THRIFT_ROOT'] . '/Type/TType.php' );
require_once( $GLOBALS['THRIFT_ROOT'] . '/Exception/TException.php' );
require_once( $GLOBALS['THRIFT_ROOT'] . '/Exception/TTransportException.php' );
require_once( $GLOBALS['THRIFT_ROOT'] . '/Exception/TProtocolException.php' );
require_once $GLOBALS['THRIFT_ROOT'].'/Types.php';
require_once $GLOBALS['THRIFT_ROOT'].'/Hbase.php';
$socket = new TSocket('localhost', '9090');
$socket->setSendTimeout(10000); // Ten seconds (too long for production, but this is just a demo ;)
$socket->setRecvTimeout(20000); // Twenty seconds
$transport = new TBufferedTransport($socket);
$protocol = new TBinaryProtocol($transport);
$client = new HbaseClient($protocol);
$transport->open();
echo nl2br( "listing tables...\n" );
$tables = $client->getTableNames();
sort($tables);
foreach ($tables as $name) {
echo( " found: {$name}\n" );
}
$columns = array(
new \Hbase\ColumnDescriptor(array(
'name' => 'id:',
'maxVersions' => 10
)),
new \Hbase\ColumnDescriptor(array(
'name' => 'name:'
)),
new \Hbase\ColumnDescriptor(array(
'name' => 'score:'
)),
);
$tableName = "student";
/*
try {
$client->createTable($tableName, $columns);
} catch (AlreadyExists $ae) {
echo( "WARN: {$ae->message}\n" );
}
*/
$descriptors = $client->getColumnDescriptors($tableName);
asort($descriptors);
foreach ($descriptors as $col) {
echo( " column: {$col->name}, maxVer: {$col->maxVersions}\n" );
}
$time = time();
var_dump($time);
$row = '2';
$valid = "foobar-".$time;
$mutations = array(
new \Hbase\Mutation(array(
'column' => 'score',
'value' => $valid
)),
);
$mutations1 = array(
new \Hbase\Mutation(array(
'column' => 'score:a',
'value' => $time,
)),
);
$attributes = array (
);
$row1 = $time;
$client->mutateRow($tableName, $row1, $mutations1, $attributes);
echo "-------write row $row1 ---\r\n";
$client->mutateRow($tableName, $row, $mutations, $attributes);
$row_name = $time;
$fam_col_name = 'score:a';
$arr = $client->get($tableName, $row_name, $fam_col_name, $attributes);
foreach ($arr as $k => $v) {
// $k = TCell
echo " ------ get one : value = {$v->value} , <br> ";
echo " ------ get one : timestamp = {$v->timestamp} <br>";
}
echo "----------\r\n";
$arr = $client->getRow($tableName, $row_name, $attributes);
// $client->getRow return a array
foreach ($arr as $k => $TRowResult) {
// $k = 0 ; non-use
// $TRowResult = TRowResult
var_dump($TRowResult);
}
echo "----------\r\n";
echo "----scanner get ------\r\n";
$startRow = '1';
$columns = array ('column' => 'score', );
//
$scan = $client->scannerOpen($tableName, $startRow, $columns, $attributes);
$nbRows = 1000;
$arr = $client->scannerGetList($scan, $nbRows);
var_dump('count of result :'.count($arr));
foreach ($arr as $k => $TRowResult) {
// code...
//var_dump($TRowResult);
}
$client->scannerClose($scan);
$transport->close();
?>
效果如下图所示
此时php读写hbase成功,个人觉得其中的问题主要出在命名空间上,需要很注意namespace和use的使用,不能漏掉任何一个可用的。