Thrift allows you to create clients to access ApsaraDB for HBase using multiple languages. The supported language packages are listed on the official website of Apache Thrift: C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml, Delphi, and other languages. The Thrift client sends requests to the ThriftServer of ApsaraDB for HBase through the Thrift protocol. The ThriftServer then reroutes the requests to the storage servers of ApsaraDB for HBase. The following figure shows the architecture.

Note: If you use ApsaraDB for HBase Performance-enhanced Edition, see APIs for multiple languages.

Activate ApsaraDB for HBase ThriftServer:

Click Activate ThriftServer service (ThriftServer high-availability version) on the cluster basic information page of the ApsaraDB for HBase console to obtain an endpoint in the format of host:port.

2. Connect to ApsaraDB for HBase

2.1. Use the Thrift client

Typically, users use Python and PHP to connect to ApsaraDB for HBase. In the following example, PHP is used to access ApsaraDB for HBase.

2.1.1. Use PHP to access ApsaraDB for HBase through Thrift.

The version of Thrift used by ApsaraDB for HBase is 0.9.0. Therefore, we recommend that you use Thrift 0.9.0 to create a client. Click here to download Thrift 0.9.0. The downloaded source code package will be used later. You must install the Thrift compiling environment first. For more information, see Thrift official website.

Run the following command to check the version of Thrift installed.

thrift --version
			

2.1.2. Obtain the HBase Thrift file for the client.

Click here to download the Hbase.thrift file used to access ApsaraDB for HBase. ApsaraDB for HBase uses the thrift1 protocol.

The command is as follows:

 thrift --gen <language> Hbase.thrift 
			

The language parameter in this command specifies the acronym of a language. The common languages are as follows:

thrift --gen php Hbase.thrift
thrift --gen cpp Hbase.thrift
thrift --gen py Hbase.thrift
			

Run the thrift --gen php Hbase.thrift command to obtain the required function package file gen-php under the directory.

thrift git:(last_dev) ✗ ll
total 56
-rw-r--r--  1 xuanling.gc  staff    24K  3  5 15:06 Hbase.thrift
drwxr-xr-x  3 xuanling.gc  staff    96B  8  1 16:03 gen-php
			

Put the Thrift folder and the gen-php file in the src directory of the workload logic code. The Thrift folder is under /lib/php/lib of the downloaded Thrift source code folder. The directory is as follows with your own client.php code:

[root@xxxxxxxxxxx thrift_client]# ll
total 12
-rw-r--r--  1 zookeeper games 2743 Aug  2 11:16 client.php
drwxr-xr-x  3 zookeeper games 4096 Aug  2 01:22 gen-php
drwxr-xr-x 12 zookeeper games 4096 Aug  2 01:22 Thrift
			

Write PHP code.

The preceding Thrift folder and the gen-php folder can be renamed as needed. In this example, we keep the default names to make it easy for you to distinguish the folders. The following PHP code shows the program that creates a table named new in ApsaraDB for HBase.

<? php
ini_set('display_errors', E_ALL);
$GLOBALS['THRIFT_ROOT'] = "/root/thrift_client";
/* Dependencies. In the proper order. */
require_once $GLOBALS['THRIFT_ROOT'] . '/Thrift/Transport/TTransport.php';
require_once $GLOBALS['THRIFT_ROOT'] . '/Thrift/Transport/TSocket.php';
require_once $GLOBALS['THRIFT_ROOT'] . '/Thrift/Protocol/TProtocol.php';
require_once $GLOBALS['THRIFT_ROOT'] . '/Thrift/Protocol/TBinaryProtocol.php';
require_once $GLOBALS['THRIFT_ROOT'] . '/Thrift/Protocol/TBinaryProtocolAccelerated.php';
require_once $GLOBALS['THRIFT_ROOT'] . '/Thrift/Transport/TBufferedTransport.php';
require_once $GLOBALS['THRIFT_ROOT'] . '/Thrift/Type/TMessageType.php';
require_once $GLOBALS['THRIFT_ROOT'] . '/Thrift/Factory/TStringFuncFactory.php';
require_once $GLOBALS['THRIFT_ROOT'] . '/Thrift/StringFunc/TStringFunc.php';
require_once $GLOBALS['THRIFT_ROOT'] . '/Thrift/StringFunc/Core.php';
require_once $GLOBALS['THRIFT_ROOT'] . '/Thrift/Type/TType.php';
require_once $GLOBALS['THRIFT_ROOT'] . '/Thrift/Exception/TException.php';
require_once $GLOBALS['THRIFT_ROOT'] . '/Thrift/Exception/TTransportException.php';
require_once $GLOBALS['THRIFT_ROOT'] . '/Thrift/Exception/TProtocolException.php';

require_once $GLOBALS['THRIFT_ROOT'] . '/gen-php/Hbase/Types.php';
require_once $GLOBALS['THRIFT_ROOT'] . '/gen-php/Hbase/Hbase.php';

use Thrift\Protocol\TBinaryProtocol;
use Thrift\Transport\TBufferedTransport;
use Thrift\Transport\TSocket;
use Hbase\HbaseClient;
use Hbase\ColumnDescriptor;
use Hbase\Mutation;

$host='hb-bp12pt6alr1788y35-001.hbase.rds.aliyuncs.com';
$port=9099;

$socket = new TSocket($host, $port);

$socket->setSendTimeout(10000); // Request sending timeout in milliseconds.
$socket->setRecvTimeout(20000); // Response reception timeout in milliseconds.
$transport = new TBufferedTransport($socket);
$protocol = new TBinaryProtocol($transport);
$client = new HbaseClient($protocol);

$transport->open();

#### List tables ####
echo "----list tables----\n";
$tables = $client->getTableNames();
foreach ($tables as $name) {
    var_dump($tables);
}

$tablename='new';
#### Write data ####
echo "----write data----\n";
$row = 'key';
$value = 'value';
$atrribute = array();
$mutations = array(
    new Mutation(array(
        'column' => 'info:cn1',
        'value' => $value
    )),
);

try {
    $client->mutateRow($tablename, $row, $mutations, $atrribute);
} catch (Exception $e) {
    var_dump($e);// Generate a debugging log
}

### Read data ####
echo "---read data---\n";
$result = $client->getRow($tablename, $row, $atrribute);
var_dump($result);

### Delete data ####
echo "---delete data---\n";
$client->deleteAllRow($tablename, $row, $atrribute);
echo "---get data---\n";
$result = $client->getRow($tablename, $row, $atrribute);
var_dump($result);

### Scan data ###
$row = 'ID1';
$value = 'v1';
$mutations = array(
   new Mutation(array(
        'column' => 'info:c1',
        'value' => $value
    )),
);
try {
    $client->mutateRow($tablename, $row, $mutations, $atrribute);
} catch (Exception $e) {
    var_dump($e);
}

$row = 'ID2';
$value = 'v2';
$mutations = array(
   new Mutation(array(
        'column' => 'info:c1',
        'value' => $value
    )),
);
try {
    $client->mutateRow($tablename, $row, $mutations, $atrribute);
} catch (Exception $e) {
    var_dump($e);
}

$row = 'ID3';
$value = 'v3';
$mutations = array(
   new Mutation(array(
        'column' => 'info:c1',
        'value' => $value
    )),
);
try {
    $client->mutateRow($tablename, $row, $mutations, $atrribute);
} catch (Exception $e) {
    var_dump($e);
}

echo 'prefix scan';
$scan = $client->scannerOpenWithPrefix($tablename, 'ID', null, null);

$nbRows = 100;
$arr = $client->scannerGetList($scan, $nbRows);
echo 'count of result :'.count($arr)."\n";
var_dump($arr);
foreach ($arr as $k => $TRowResult) {
   echo "\trow:$TRowResult->row\tcolumns(array):";
   foreach ($TRowResult->columns as $key => $value) {
      echo "key:$key\tvalue:$value->value\ttimestamp:$value->timestamp\n";
   }
}

echo 'range scan';
$scan = $client->scannerOpenWithStop($tablename, 'ID0', 'ID2', null, null);

$nbRows = 100;
$arr = $client->scannerGetList($scan, $nbRows);
echo 'count of result :'.count($arr)."\n";
var_dump($arr);
foreach ($arr as $k => $TRowResult) {
   echo "\trow:$TRowResult->row\tcolumns(array):";
   foreach ($TRowResult->columns as $key => $value) {
      echo "key:$key\tvalue:$value->value\ttimestamp:$value->timestamp\n";
   }
}

### Increment operation ###
echo "do increment on a new row";
$row = 'ID4';
try {
$newCount = $client->atomicIncrement($tablename, $row, 'info:c1', 1234);
} catch (Exception $e) {
    var_dump($e);
}

echo "new count $newCount\n";

### Write long-type data to ApsaraDB for HBase ###

$row = 'ID5';
$value = pack("J", 4567);

$mutations = array(
   new Mutation(array(
        'column' => 'info:c1',
        'value' => $value
    )),
);
try {
    $client->mutateRow($tablename, $row, $mutations, null);
} catch (Exception $e) {
    var_dump($e);
}

echo "---read data and print it as long ---\n";
$result = $client->getRow($tablename, $row, null);

foreach ($result[0]->columns as $key => $value) {
  $count = unpack("J*mycount", $value->value);
  var_dump($count);
}

? >
			

The execution result is as follows:

[root@xxxxxxxxxxx thrift_client]# php client.php
----list tables----
array(1) {
  [0]=>
  string(3) "new"
}
----write data----
---read data---
array(1) {
  [0]=>
  object(Hbase\TRowResult)#8 (3) {
    ["row"]=>
    string(3) "key"
    ["columns"]=>
    array(1) {
      ["info:cn1"]=>
      object(Hbase\TCell)#10 (2) {
        ["value"]=>
        string(5) "value"
        ["timestamp"]=>
        int(1533179795969)
      }
    }
    ["sortedColumns"]=>
    NULL
  }
}
---delete data---
---get data---
array(0) {
}
			

2.2. Use Python to connect to ApsaraDB for HBase

Some users may access the ThriftServer by using a third-party library in Python such as HappyBase. The third-party library includes Thrift. For more information, see Installation guide. There are various of Python libraries, and you can install Thrift and access the HBase Thrift library through pip. Assuming that you have installed Python and pip, the execution process is as follows:

pip install thrift // Install the latest version of Thrift by default.
pip install hbase-thrift // Install the HBase Thrift interface library.
			

You can write the code to access ApsaraDB for HBase after the preceding two steps are complete.

import sys
import time
import os

from thrift import Thrift
from thrift.transport import TSocket, TTransport
from thrift.protocol import TBinaryProtocol
from thrift.protocol.TBinaryProtocol import TBinaryProtocolAccelerated
from hbase import ttypes
from hbase.Hbase import Client, ColumnDescriptor, Mutation

def printRow(entry):
  print "row: " + entry.row + ", cols:",
  for k in sorted(entry.columns):
    print k + " => " + entry.columns[k].value,
  print


transport = TSocket.TSocket('hb-bp12pt6alr1788y35-001.hbase.rds.aliyuncs.com', 9099)
transport = TTransport.TBufferedTransport(transport)
protocol = TBinaryProtocol.TBinaryProtocolAccelerated(transport)
client = Client(protocol)
transport.open()

print "---list table--"
print client.getTableNames()

table="new"
row="key"

print "---write data---"
mutations = [Mutation(column="info:cn1", value="value")]
client.mutateRow(table, row, mutations)

print "---get data----"
printRow(client.getRow(table, row)[0])

print "---delete data---"
client.deleteAllRow(table, row)
print "---end----"

transport.close()
			

The execution result is as follows:

[root@Test ~]# python Hbase_client.py
---list table--
['new']
---write data---
---get data----
row: key, cols: info:cn1 => value
---delete data---
---end----
			

Access ApsaraDB for HBase using Go

Download the optimized Thrift access package and decompress it into $GOPATH/src directory. You can also choose to download the original version from https://github.com/sdming/goh.

wget http://public-hbase.oss-cn-hangzhou.aliyuncs.com/thrift/goh.tar.gz
tar -xvzf goh.tar.gz
mv github.com $GOPATH/src
			

For more information about the sample code, see $GOPATH/src/github.com/sdming/goh/demo/client.go that contains DDL, and sample code for reading and writing data.