背景
近期有通過go語言訪問阿里雲hbase增強版的需求,博主進行簡單實現,並且加以記錄。主要藉助了thrift和github.com/silenceper/pool的連接池實現。
實戰
阿里雲提供的thrift連接hbase的demo
參考文檔:https://github.com/aliyun/aliyun-apsaradb-hbase-demo/tree/master/hbase/thrift2/go?spm=a2c4g.11186623.2.30.69f329aa8PJzw2
看了一下demo,代碼畢竟簡單:
- 創建client
- 利用client進行增刪改查等操作
但是有一點需求注意:thrift的client是線程不安全的(言外之意,多線程訪問必須要使用不同的client實例),爲此,必須要引入連接池。
silenceper連接池
博主直接使用:github.com/silenceper/pool
大體看了一下代碼,流程如下:
- 創建連接池配置(例如:最大連接數、idle連接數等)
- 根據配置,創建連接池
- 獲取連接
- 業務處理
- 返還連接
實現代碼
package main
import (
"./gen-go/hbase"
"context"
"fmt"
"github.com/apache/thrift/lib/go/thrift"
"github.com/silenceper/pool"
"time"
"unsafe"
)
const (
HOST = "xxxxxxxxxxxxxxxx"
// 用戶名
USER = "xxx"
// 密碼
PASSWORD = "xxxx"
)
// 創建連接
func getHbaseClient() (interface{}, error) {
protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
trans, err := thrift.NewTHttpClient(HOST)
if err != nil {
return nil, err
}
// 設置用戶名密碼
httClient := trans.(*thrift.THttpClient)
httClient.SetHeader("ACCESSKEYID", USER)
httClient.SetHeader("ACCESSSIGNATURE", PASSWORD)
if err := trans.Open(); err != nil {
return nil, err
}
return hbase.NewTHBaseServiceClientFactory(trans, protocolFactory), nil
}
// 關閉連接(這裏暫不考慮)
func clientClose(client interface{}) error {
return nil
}
func main() {
tableInbytes := []byte("ns:table1")
defaultCtx := context.Background()
// 創建連接池配置
poolConfig := &pool.Config{
InitialCap: 2,
MaxIdle: 4,
MaxCap: 5,
Factory: getHbaseClient,
Close: clientClose,
IdleTimeout: 300 * time.Second,
}
// 創建連接池
p, _ := pool.NewChannelPool(poolConfig)
time.Sleep(2 * time.Second)
// 併發獲取連接
go asyncPrint(p, defaultCtx, tableInbytes)
go asyncPrint(p, defaultCtx, tableInbytes)
go asyncPrint(p, defaultCtx, tableInbytes)
go asyncPrint(p, defaultCtx, tableInbytes)
time.Sleep(2 * time.Second)
go asyncPrint(p, defaultCtx, tableInbytes)
go asyncPrint(p, defaultCtx, tableInbytes)
go asyncPrint(p, defaultCtx, tableInbytes)
time.Sleep(10 * time.Second)
}
func asyncPrint(p pool.Pool, ctx context.Context, tableInBytes []byte) {
client, _ := p.Get()
res, _ := client.(*hbase.THBaseServiceClient).Get(ctx, tableInBytes, &hbase.TGet{Row: []byte("row1")})
fmt.Println(res)
_ = p.Put(client)
}
評價
實現了初步通過thrift訪問hbase的操作。
後續需要確認:
- 連接長時間沒有數據交互的情況處理(考慮ping操作)
- close連接的操作