【发布时间】:2021-04-08 09:38:16
【问题描述】:
我有一个 Go REST 服务,它连接到 DynamoDB 以检索一些产品。该表有大约 100.000 个产品,我通常检索大约 20.0000 个(然后在实际回复之前被其他进程过滤掉,但这与我的问题无关)。
我看到的问题是我的整个请求大约需要 4 秒,这对我的目标来说非常高。我开始在我的应用程序中记录每一层,直到最终到达最小的部分,即从数据库中检索一个项目的每个单独的部分。
令我惊讶的是,每个项目检索大约需要 3.6 秒??!!。
不管下面的代码,这可能是什么原因?我在发电机的配置上缺少什么吗?
func (db DynamoRepository) FetchProducts(c *gin.Context, pID string) ([]models.Product, error) {
output := make([]models.Product, 0)
chProduct := make(chan *models.Product)
sem := make(chan struct{}, 40000)
wait := sync.WaitGroup{}
wait.Add(1)
go func (wg *sync.WaitGroup) {
defer wg.Done()
for i := 0; i < len(itemIDs); i++ {
p := <-chProduct
if p != nil {
output = append(output, *p)
}
}
close(chProduct)
}(&wait)
for index := range itemIDs {
sem <- struct{}{}
go func(ix int, s chan struct{}, ch chan *models.Product) {
defer func() {
<- s
}()
infoSlice := strings.Split(itemIDs[ix], "_")
if len(infoSlice) != 2 {
ch <- nil
return
}
key := map[string]*dynamodb.AttributeValue{
"PK": {
N: aws.String(pID),
},
"SK": {
S: aws.String("product"),
},
}
start := time.Now()
result, err := db.DB.GetByKey(c, db.Config.AWS.Table, key)
fmt.Printf("Item %s took %d\n", productID, time.Since(start).Milliseconds())
if err != nil {
ch <- nil
return
}
if result.Item == nil {
ch <- nil
return
}
var product models.Product
err = dynamodbattribute.UnmarshalMap(result.Item, &product)
if err != nil {
ch <- nil
return
}
ch <- &product
}(index, sem, chProduct)
}
wait.Wait()
if len(output) == 0 {
return nil, nil
}
return output, nil
}
GetByKey的实现:
func (provider *DynamoDBProvider) GetByKey(ctx context.Context, tableName string, key map[string]*dynamodb.AttributeValue) (*dynamodb.GetItemOutput, error) {
input := &dynamodb.GetItemInput{
TableName: aws.String(tableName),
Key: key,
}
result, err := provider.client.GetItem(input)
return result, err
}
【问题讨论】:
-
当使用其他客户端连接到您的DynamoDB实例时,时间上的差异有多大?这可能是网络延迟问题。此外,BatchGetItem 允许您一次获取多达 100 个对象,这比单独获取它们要快得多。
-
嗨 Mikael,我最终会将实现更改为 BatchGetItem,但这个问题仍然会大大减慢进程。
-
对于其他客户端,其他 Go 项目使用相同的 SDK,并且对他们来说工作正常
-
您的容量是按需还是预配?
-
您的后台吞吐量是多少?如果您的读取次数从 0 次增加到 20,000 次,DynamoDB 不太可能立即扩展吞吐量。如果您重复测试(即预热数据库),您的响应时间会缩短吗?
标签: go amazon-dynamodb