使用 Golang 减少访问 Bigtable 的时间
Reduce access time to Bigtable with Golang
我想减少在我的 Golang RestApi 上访问我的 table 的时间。
我有一个带有 enpoint 的 Go restAPI,它需要为请求正文中指定的每个代码访问一个大的table 数据库。我设计的访问键是"provider|client|productCode|date|.."(以及其他4个参数)。
对于请求正文的每个 productCode,我进行异步调用以读取具有指定键的行。
在我的测试中,我请求了 1000 个产品代码,在我的本地机器上获取的时间约为 800~900 毫秒。云机器上的时间约为 550~450 毫秒。
我正在使用 bigtable package 访问 bigTable,我正在使用以下代码:
package main
import (
"log"
"time"
"golang.org/x/net/context"
"google.golang.org/cloud/bigtable"
)
func main() {
start2 := time.Now()
listPKs := []string{"PROV|CLI|6030|20160714|8|30301.30302|ES", "PROV|CLI|44103|20160714|8|30301.30302|ES", "PROV|CLI|1454871|20160714|8|30301.30302|ES"}
providerRS := getBDresponse(listPKs, 50000)
if providerRS != nil {
///do something
}
elapsed2 := time.Since(start2)
log.Printf("Time access BT: %s", elapsed2)
}
func getBDresponse(listPKs []string, timeoutMiliseconds int) []string {
resp := make(chan string)
table := myClient.Client.Open(TABLE_NAME)
//async call to BT
for _, key := range listPKs {
go asyncDoUniqueCall(key, resp, myContext, table)
}
//get all responses
providerRS := getResponses(resp, timeoutMiliseconds, len(listPKs))
return providerRS
}
func asyncDoUniqueCall(pk string, ch chan string, ctx *context.Context, table *bigtable.Table) {
ch <- GetRowValue(pk, ctx, table)
}
func getResponses(resp chan string, timeoutMiliseconds int, totalNumRQ int) []string {
var ret []string
for j := 0; j < totalNumRQ; j++ {
select {
case rowResponse := <-resp: //catch the response
if rowResponse != "" {
ret = append(ret, rowResponse)
}
case <-time.After(time.Duration(timeoutMiliseconds) * time.Millisecond): // timeout control
return nil
}
}
return ret
}
//GetRowValue open the table and get the row indexed by pk and returns the stored message
func GetRowValue(pk string, ctx *context.Context, table *bigtable.Table) string {
var response string
r, err := table.ReadRow(*ctx, pk)
if err != nil {
return ""
}
if len(r) > 0 {
row := r[COLUMN_FAMILY_NAME]
numCol := len(row)
response = string(row[0].Value)
}
return response
}
我也尝试了 this 示例,但时间并不好:
我使用的是 gorutines 和 chanels correctyl 吗?
我访问 BT 的方式是否正确?
也许按键设计不正确?
我认为问题在于您使用的是一维 chan
:
resp := make(chan string)
您应该尝试通过以下方式扩大其维度:
resp := make(chan string,len(listPKs))
这是因为如果您的异步函数在读取 chan
中的信息之前完成,那么 chan
将被阻塞。
旁注:在不执行任何检查的情况下生成 go 例程可能是问题的可能来源。
我建议您实施 working queue 以优化您的任务。
我想减少在我的 Golang RestApi 上访问我的 table 的时间。
我有一个带有 enpoint 的 Go restAPI,它需要为请求正文中指定的每个代码访问一个大的table 数据库。我设计的访问键是"provider|client|productCode|date|.."(以及其他4个参数)。
对于请求正文的每个 productCode,我进行异步调用以读取具有指定键的行。
在我的测试中,我请求了 1000 个产品代码,在我的本地机器上获取的时间约为 800~900 毫秒。云机器上的时间约为 550~450 毫秒。
我正在使用 bigtable package 访问 bigTable,我正在使用以下代码:
package main
import (
"log"
"time"
"golang.org/x/net/context"
"google.golang.org/cloud/bigtable"
)
func main() {
start2 := time.Now()
listPKs := []string{"PROV|CLI|6030|20160714|8|30301.30302|ES", "PROV|CLI|44103|20160714|8|30301.30302|ES", "PROV|CLI|1454871|20160714|8|30301.30302|ES"}
providerRS := getBDresponse(listPKs, 50000)
if providerRS != nil {
///do something
}
elapsed2 := time.Since(start2)
log.Printf("Time access BT: %s", elapsed2)
}
func getBDresponse(listPKs []string, timeoutMiliseconds int) []string {
resp := make(chan string)
table := myClient.Client.Open(TABLE_NAME)
//async call to BT
for _, key := range listPKs {
go asyncDoUniqueCall(key, resp, myContext, table)
}
//get all responses
providerRS := getResponses(resp, timeoutMiliseconds, len(listPKs))
return providerRS
}
func asyncDoUniqueCall(pk string, ch chan string, ctx *context.Context, table *bigtable.Table) {
ch <- GetRowValue(pk, ctx, table)
}
func getResponses(resp chan string, timeoutMiliseconds int, totalNumRQ int) []string {
var ret []string
for j := 0; j < totalNumRQ; j++ {
select {
case rowResponse := <-resp: //catch the response
if rowResponse != "" {
ret = append(ret, rowResponse)
}
case <-time.After(time.Duration(timeoutMiliseconds) * time.Millisecond): // timeout control
return nil
}
}
return ret
}
//GetRowValue open the table and get the row indexed by pk and returns the stored message
func GetRowValue(pk string, ctx *context.Context, table *bigtable.Table) string {
var response string
r, err := table.ReadRow(*ctx, pk)
if err != nil {
return ""
}
if len(r) > 0 {
row := r[COLUMN_FAMILY_NAME]
numCol := len(row)
response = string(row[0].Value)
}
return response
}
我也尝试了 this 示例,但时间并不好:
我使用的是 gorutines 和 chanels correctyl 吗? 我访问 BT 的方式是否正确? 也许按键设计不正确?
我认为问题在于您使用的是一维 chan
:
resp := make(chan string)
您应该尝试通过以下方式扩大其维度:
resp := make(chan string,len(listPKs))
这是因为如果您的异步函数在读取 chan
中的信息之前完成,那么 chan
将被阻塞。
旁注:在不执行任何检查的情况下生成 go 例程可能是问题的可能来源。
我建议您实施 working queue 以优化您的任务。