诊断和排查 Azure Cosmos DB 的“未找到”异常
适用范围: NoSQL
HTTP 状态代码 404 表示资源不再存在。
预期行为
应用程序预期接收代码 404 并正确进行处理的有效方案有许多。
对应该存在或确实存在的项返回了“未找到”异常
以下是在该项应该或确实存在的情况下返回状态代码 404 的可能原因。
读取会话不可用于输入会话令牌
解决方案:
- 将当前 SDK 更新到已发布的最新版本。 此特定错误的最常见原因问题已在最新版 SDK 中得到解决。
争用条件
有多个 SDK 客户端实例且读取在写入之前发生。
解决方案:
- Azure Cosmos DB 的默认帐户一致性为会话一致性。 创建或更新项时,响应将返回一个会话令牌,该令牌可以在 SDK 实例之间传递,以确保读取请求在从具有该更改的副本中进行读取。
- 将一致性级别更改为更高级别。
读取容器或数据库资源的吞吐量
使用 PowerShell 或 Azure CLI 并收到“未找到”错误消息。
解决方案:
可以在数据库级别和/或容器级别预配吞吐量。 如果收到“未找到”错误,请尝试读取父数据库资源或子容器资源的吞吐量。
分区键和 ID 组合无效
分区键和 ID 组合无效。
解决方案:
修复导致错误组合的应用程序逻辑。
项 ID 中的字符无效
项已插入 Azure Cosmos DB,并且项 ID 中带有无效字符。
解决方案:
将 ID 更改为不包含特殊字符的其他值。 如果不能更改 ID,则可以对 ID 进行 Base64 编码以将特殊字符转义。 Base64 仍然会生成一个包含无效字符“/”的名称,该字符需要替换。
对于已经插入容器中的项,可以使用 RID 值来替换其 ID,而不使用基于名称的引用。
// Get a container reference that uses RID values.
ContainerProperties containerProperties = await this.Container.ReadContainerAsync();
string[] selfLinkSegments = containerProperties.SelfLink.Split('/');
string databaseRid = selfLinkSegments[1];
string containerRid = selfLinkSegments[3];
Container containerByRid = this.cosmosClient.GetContainer(databaseRid, containerRid);
// Invalid characters are listed here.
// https://learn.microsoft.com/dotnet/api/microsoft.azure.documents.resource.id#remarks
FeedIterator<JObject> invalidItemsIterator = this.Container.GetItemQueryIterator<JObject>(
@"select * from t where CONTAINS(t.id, ""/"") or CONTAINS(t.id, ""#"") or CONTAINS(t.id, ""?"") or CONTAINS(t.id, ""\\"") ");
while (invalidItemsIterator.HasMoreResults)
{
foreach (JObject itemWithInvalidId in await invalidItemsIterator.ReadNextAsync())
{
// Choose a new ID that doesn't contain special characters.
// If that isn't possible, then Base64 encode the ID to escape the special characters.
byte[] plainTextBytes = Encoding.UTF8.GetBytes(itemWithInvalidId["id"].ToString());
itemWithInvalidId["id"] = Convert.ToBase64String(plainTextBytes).Replace('/', '!');
// Update the item with the new ID value by using the RID-based container reference.
JObject item = await containerByRid.ReplaceItemAsync<JObject>(
item: itemWithInvalidId,
ID: itemWithInvalidId["_rid"].ToString(),
partitionKey: new Cosmos.PartitionKey(itemWithInvalidId["status"].ToString()));
// Validating the new ID can be read by using the original name-based container reference.
await this.Container.ReadItemAsync<ToDoActivity>(
item["id"].ToString(),
new Cosmos.PartitionKey(item["status"].ToString())); ;
}
}
生存时间清除
项已设置生存时间 (TTL) 属性。 由于 TTL 属性已过期,项被清除。
解决方案:
更改 TTL 属性以防止清除该项。
惰性索引编制
惰性索引编制未跟进。
解决方案:
等待索引编制跟进或更改索引编制策略。
已删除父资源
项所在的数据库或容器已删除。
解决方案:
- 从备份还原父资源或重新创建资源。
- 创建新资源来替换已删除的资源。
7.容器/集合名称区分大小写
容器/集合名称在 Azure Cosmos DB 中区分大小写。
解决方案:
请确保在连接到 Azure Cosmos DB 时使用准确的名称。
后续步骤
- 诊断和排查在使用 Azure Cosmos DB .NET SDK 时遇到的问题。
- 了解 .NET v3 和 .NET v2 的性能准则。
- 诊断和排查使用 Azure Cosmos DB Java v4 SDK 时遇到的问题。
- 了解 Java v4 SDK 的性能准则。