AmazonDynamoDB获取记录需要很长时间,延迟高达5-6秒



pom.xml

<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-bom</artifactId>
<version>1.11.256</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-dynamodb</artifactId>
</dependency>

客户代码

public static AmazonDynamoDB getDynamoDBClient() {
return AmazonDynamoDBClientBuilder.standard().withRegion("ap-southeast-1").build();
}

现在我正在尝试执行一个记录很少的普通查询,但获取结果需要很长时间。

它第一次在大约5-6秒内对多个请求提取记录,减少了一半。2-3秒对于只获取少量物品来说仍然是一个很大的时间。

已经使用不同的客户端配置(连接超时、请求超时、重试等)检查了DynamoDB的调优,但没有给出预期的结果。还检查了SDK版本2的URLConnectionHTTPClient配置,但也得到了相同的结果。

一个可能的原因可能是dynamo DB客户端的凭据获取时间,但在java中没有任何凭据缓存引用。有人能建议可能的配置来改善这种延迟吗。

它第一次在大约5-6秒内对多个请求获取记录,减少了一半。2-3秒对于只获取少量物品来说仍然是一个很大的时间。

即使在生产中使用dynamo也会出现这种情况,因为第一次获取以下操作序列时会发生:-

  1. 从路由表中查找您请求的数据所属的分区ID
  2. 缓存Partiton的关键
  3. 然后引用用于获取数据的分区

如您所见,步骤2中有缓存,因此下次请求进行时,会从缓存中提取分区id,从而降低延迟。(一旦我有了它,就会分享来源)

任何人都可以建议可能的配置来改善这种延迟吗。

此外,请不要使用本地发电机进行性能基准测试,因为它内部使用SQLite,即用于存储的SQL DB。参考:-https://www.dbi-services.com/blog/aws-dynamodb-local/#:~:text=Yes%2C%20this%20NoSQL%20database%20is,Local%20engine%2C%20%embedded%20in%20Java。

您使用的是非常旧的API,不再是最佳实践。要使用Java的最佳实践,请使用AWS SDK for Java v2

Java2.x的AWS SDK是对1.x版本代码库的主要重写。它构建在Java8+之上,并添加了一些经常需要的功能。其中包括对非阻塞I/O的支持,以及在运行时插入不同HTTP实现的能力

v2的POM是:

<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.17.190</version>
<type>pom</type>
<scope>import</scope>
</dependency>

要使用AWS SDK for Java v2检索记录,您有三个选择。

  • 使用DynamoDbClient
  • 使用增强型客户端(将Java对象映射到表)
  • 使用PartiQL(使用类似SQL的语法)

我会告诉你所有的方法。所有示例都可以在AmazonGithub repo中找到。

使用DynamoDbClient

代码为:

package com.example.dynamodb;
// snippet-start:[dynamodb.java2.get_item.import]
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
// snippet-end:[dynamodb.java2.get_item.import]

/**
* Before running this Java V2 code example, set up your development environment, including your credentials.
*
* For more information, see the following documentation topic:
*
* https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
*
* To get an item from an Amazon DynamoDB table using the AWS SDK for Java V2, its better practice to use the
* Enhanced Client, see the EnhancedGetItem example.
*/
public class GetItem {
public static void main(String[] args) {
final String usage = "n" +
"Usage:n" +
"    <tableName> <key> <keyVal>nn" +
"Where:n" +
"    tableName - The Amazon DynamoDB table from which an item is retrieved (for example, Music3). n" +
"    key - The key used in the Amazon DynamoDB table (for example, Artist). n" +
"    keyval - The key value that represents the item to get (for example, Famous Band).n" ;
if (args.length != 3) {
System.out.println(usage);
System.exit(1);
}
String tableName = "Customer" ; //args[0];
String key = "id" ; //args[1];
String keyVal = "id101" ; //args[2];
System.out.format("Retrieving item "%s" from "%s"n", keyVal, tableName);
ProfileCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create();
Region region = Region.US_EAST_1;
DynamoDbClient ddb = DynamoDbClient.builder()
.credentialsProvider(credentialsProvider)
.region(region)
.build();
getDynamoDBItem(ddb, tableName, key, keyVal);
ddb.close();
}
// snippet-start:[dynamodb.java2.get_item.main]
public static void getDynamoDBItem(DynamoDbClient ddb,String tableName,String key,String keyVal ) {
HashMap<String,AttributeValue> keyToGet = new HashMap<>();
keyToGet.put(key, AttributeValue.builder()
.s(keyVal).build());
GetItemRequest request = GetItemRequest.builder()
.key(keyToGet)
.tableName(tableName)
.build();
try {
Map<String,AttributeValue> returnedItem = ddb.getItem(request).item();
if (returnedItem != null) {
Set<String> keys = returnedItem.keySet();
System.out.println("Amazon DynamoDB table attributes: n");
for (String key1 : keys) {
System.out.format("%s: %sn", key1, returnedItem.get(key1).toString());
}
} else {
System.out.format("No item found with the key %s!n", key);
}
} catch (DynamoDbException e) {
System.err.println(e.getMessage());
System.exit(1);
}
}
// snippet-end:[dynamodb.java2.get_item.main]
}

增强型客户端

代码为:

package com.example.dynamodb;
// snippet-start:[dynamodb.java2.mapping.getitem.import]
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.Key;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
// snippet-end:[dynamodb.java2.mapping.getitem.import]
/*
* Before running this code example, create an Amazon DynamoDB table named Customer with these columns:
*   - id - the id of the record that is the key
*   - custName - the customer name
*   - email - the email value
*   - registrationDate - an instant value when the item was added to the table
*
* Also, ensure that you have set up your development environment, including your credentials.
*
* For information, see this documentation topic:
*
* https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
*/
public class EnhancedGetItem {
public static void main(String[] args) {
ProfileCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create();
Region region = Region.US_EAST_1;
DynamoDbClient ddb = DynamoDbClient.builder()
.credentialsProvider(credentialsProvider)
.region(region)
.build();
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
.dynamoDbClient(ddb)
.build();
getItem(enhancedClient);
ddb.close();
}
// snippet-start:[dynamodb.java2.mapping.getitem.main]
public static void getItem(DynamoDbEnhancedClient enhancedClient) {
try {
DynamoDbTable<Customer> table = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class));
Key key = Key.builder()
.partitionValue("id120")
.build();
// Get the item by using the key.
Customer result = table.getItem(r->r.key(key));
System.out.println("******* The description value is "+result.getCustName());
} catch (DynamoDbException e) {
System.err.println(e.getMessage());
System.exit(1);
}
}
// snippet-end:[dynamodb.java2.mapping.getitem.main]
}

PartiQL

代码为

public static void getItem(DynamoDbClient ddb) {
String sqlStatement = "SELECT * FROM MoviesPartiQ where year=? and title=?";
List<AttributeValue> parameters = new ArrayList<>();
AttributeValue att1 = AttributeValue.builder()
.n("2012")
.build();
AttributeValue att2 = AttributeValue.builder()
.s("The Perks of Being a Wallflower")
.build();
parameters.add(att1);
parameters.add(att2);
try {
ExecuteStatementResponse response = executeStatementRequest(ddb, sqlStatement, parameters);
System.out.println("ExecuteStatement successful: "+ response.toString());
} catch (DynamoDbException e) {
System.err.println(e.getMessage());
System.exit(1);
}
}

所有这些方法都建议使用AWS SDK for Java V1。如果您不熟悉V2 API,包括cred和设置您的开发环境,请参阅:

开发者指南-AWS SDK for Java 2.x

最新更新