如何解决从 Azure Function 向 Azure Cosmos 缓慢插入的问题
How to troubleshoot slow inserts to Azure Cosmos from Azure Function
我想使用 Cosmos .NET SDK v3 将小文档(<10 JSON 个字段)从 Azure Function 插入到 Azure Cosmos DB,但每次插入需要 1-2 秒。
插入代码为
await container.CreateItemAsync(
objectToAdd,
new PartitionKey(objectToAdd.PartitionKey),
new ItemRequestOptions { EnableContentResponseOnWrite = false })
查看诊断,大部分时间是在项目流式传输期间花费的(请参阅末尾的日志)。
Azure Functions和Cosmos都部署在同一个区域(北欧)。 Cosmos 允许通过启用 vnet 的服务端点访问 Azure Functions。
我已通读 https://blog.tdwright.co.uk/2019/06/29/aggressively-tuning-cosmos-db-the-long-way-round/ and https://docs.microsoft.com/en-us/azure/cosmos-db/performance-tips-dotnet-sdk-v3-sql 尝试了以下内容:
- 同时使用直接和网关连接模式(未发现显着差异)。
- 禁用写入操作的内容响应(这将写入时间减少到 250 毫秒到 500 毫秒左右)。
- 确保有单例
CosmosClient
我没试过:
- 增加数据库中的 RU,因为我只测试少量 7.6 RU 插入。
- 使用批量库,因为文档是单独到达的
对于应该完全在单个数据中心内的东西来说,这似乎是一个很长的响应时间。
我的问题:
- 以上信息是不是网络问题?
- 如果是这样,Cosmos 是否提供了一种在 Azure 中跟踪连接的方法,有点像 TRACERT 所做的那样?
- Cosmos 是否记录它认为连接源自的 IP 地址?
- 或者代码层面是否有进一步的优化可能?
{
"Summary": {
"StartUtc": "2020-10-22T21:21:03.3520979Z",
"ElapsedTime": "00:00:01.0030109",
"UserAgent": "cosmos-netstandard-sdk/3.6.0|3.4.2|38128|X86|Microsoft Windows 10.0.14393 |.NET Core 4.6.29215.02|"
},
"Context": [
{
"Id": "ItemStream",
"ElapsedTime": "00:00:01.0030109"
},
{
"Id": "ItemSerialize",
"ElapsedTime": "00:00:00.0000212"
},
{
"Id": "ExtractPkValue",
"ElapsedTime": "00:00:00.0000402"
},
{
"Id": "BatchAsyncContainerExecutor.Limiter",
"ElapsedTime": "00:00:00.0000056"
},
{
"Id": "RequestInvokerHandler",
"ElapsedTime": "00:00:00.0071549"
},
{
"Id": "Microsoft.Azure.Cosmos.Handlers.RetryHandler",
"ElapsedTime": "00:00:00.0071272"
},
{
"Id": "Microsoft.Azure.Cosmos.Handlers.RouterHandler",
"ElapsedTime": "00:00:00.0070979"
},
{
"Id": "TransportHandler",
"ElapsedTime": "00:00:00.0070954"
},
{
"Id": "PointOperationStatistics",
"ActivityId": "...",
"StatusCode": 200,
"SubStatusCode": 0,
"RequestCharge": 7.62,
"RequestUri": "...",
"RequestSessionToken": null,
"ResponseSessionToken": "..",
"ClientRequestStats": {
"RequestStartTimeUtc": "2020-10-22T21:21:04.3479626Z",
"RequestEndTimeUtc": "2020-10-22T21:21:04.3548940Z",
"RequestLatency": "00:00:00.0069314",
"IsCpuOverloaded": false,
"NumberRegionsAttempted": 1,
"ResponseStatisticsList": [
{
"ResponseTime": "2020-10-22T21:21:04.354894Z",
"ResourceType": 2,
"OperationType": 40,
"StoreResult": "StorePhysicalAddress: rntbd://cdb-ms-prod-northeurope1-fd8.documents.azure.com:14173/apps/.../, LSN: 304, GlobalCommittedLsn: 303, PartitionKeyRangeId: 0, IsValid: True, StatusCode: 200, SubStatusCode: 0, RequestCharge: 7.62, ItemLSN: -1, SessionToken: ..., UsingLocalLSN: False, TransportException: null"
}
],
"AddressResolutionStatistics": [],
"SupplementalResponseStatistics": [],
"FailedReplicas": [],
"RegionsContacted": [
"<redacted>"
],
"ContactedReplicas": [
"rntbd://cdb-ms-prod-northeurope1-fd8.documents.azure.com:14173/apps/<redacted>/",
"rntbd://cdb-ms-prod-northeurope1-fd8.documents.azure.com:14387/apps/<redacted>/",
"rntbd://cdb-ms-prod-northeurope1-fd8.documents.azure.com:14215/apps/<redacted>/",
"rntbd://cdb-ms-prod-northeurope1-fd8.documents.azure.com:14064/apps/<redacted>/"
]
}
},
{
"Id": "BatchAsyncContainerExecutor.ToResponse",
"ElapsedTime": "00:00:00.0000295"
}
]
}
您似乎在使用批量模式。请记住,批量模式是一种在发送大量操作时使 RU 饱和的模式。你提到你要发送 < 10,所以我建议(除非你有发送更多的情况)在这种情况下你不要使用批量模式。
另请检查:
- 您使用的是 Singleton CosmosClient 吗?
- 实例 运行 是否与您的写入 Cosmos DB 区域位于同一区域?
- 更新您的 SDK,您使用的是 3.6.0 版,在 3.11.0 中对 Bulk(如果您仍想使用 Bulk)进行了改进,使其在文档数量较少的情况下速度更快。
我想使用 Cosmos .NET SDK v3 将小文档(<10 JSON 个字段)从 Azure Function 插入到 Azure Cosmos DB,但每次插入需要 1-2 秒。
插入代码为
await container.CreateItemAsync(
objectToAdd,
new PartitionKey(objectToAdd.PartitionKey),
new ItemRequestOptions { EnableContentResponseOnWrite = false })
查看诊断,大部分时间是在项目流式传输期间花费的(请参阅末尾的日志)。
Azure Functions和Cosmos都部署在同一个区域(北欧)。 Cosmos 允许通过启用 vnet 的服务端点访问 Azure Functions。
我已通读 https://blog.tdwright.co.uk/2019/06/29/aggressively-tuning-cosmos-db-the-long-way-round/ and https://docs.microsoft.com/en-us/azure/cosmos-db/performance-tips-dotnet-sdk-v3-sql 尝试了以下内容:
- 同时使用直接和网关连接模式(未发现显着差异)。
- 禁用写入操作的内容响应(这将写入时间减少到 250 毫秒到 500 毫秒左右)。
- 确保有单例
CosmosClient
我没试过:
- 增加数据库中的 RU,因为我只测试少量 7.6 RU 插入。
- 使用批量库,因为文档是单独到达的
对于应该完全在单个数据中心内的东西来说,这似乎是一个很长的响应时间。
我的问题:
- 以上信息是不是网络问题?
- 如果是这样,Cosmos 是否提供了一种在 Azure 中跟踪连接的方法,有点像 TRACERT 所做的那样?
- Cosmos 是否记录它认为连接源自的 IP 地址?
- 或者代码层面是否有进一步的优化可能?
{
"Summary": {
"StartUtc": "2020-10-22T21:21:03.3520979Z",
"ElapsedTime": "00:00:01.0030109",
"UserAgent": "cosmos-netstandard-sdk/3.6.0|3.4.2|38128|X86|Microsoft Windows 10.0.14393 |.NET Core 4.6.29215.02|"
},
"Context": [
{
"Id": "ItemStream",
"ElapsedTime": "00:00:01.0030109"
},
{
"Id": "ItemSerialize",
"ElapsedTime": "00:00:00.0000212"
},
{
"Id": "ExtractPkValue",
"ElapsedTime": "00:00:00.0000402"
},
{
"Id": "BatchAsyncContainerExecutor.Limiter",
"ElapsedTime": "00:00:00.0000056"
},
{
"Id": "RequestInvokerHandler",
"ElapsedTime": "00:00:00.0071549"
},
{
"Id": "Microsoft.Azure.Cosmos.Handlers.RetryHandler",
"ElapsedTime": "00:00:00.0071272"
},
{
"Id": "Microsoft.Azure.Cosmos.Handlers.RouterHandler",
"ElapsedTime": "00:00:00.0070979"
},
{
"Id": "TransportHandler",
"ElapsedTime": "00:00:00.0070954"
},
{
"Id": "PointOperationStatistics",
"ActivityId": "...",
"StatusCode": 200,
"SubStatusCode": 0,
"RequestCharge": 7.62,
"RequestUri": "...",
"RequestSessionToken": null,
"ResponseSessionToken": "..",
"ClientRequestStats": {
"RequestStartTimeUtc": "2020-10-22T21:21:04.3479626Z",
"RequestEndTimeUtc": "2020-10-22T21:21:04.3548940Z",
"RequestLatency": "00:00:00.0069314",
"IsCpuOverloaded": false,
"NumberRegionsAttempted": 1,
"ResponseStatisticsList": [
{
"ResponseTime": "2020-10-22T21:21:04.354894Z",
"ResourceType": 2,
"OperationType": 40,
"StoreResult": "StorePhysicalAddress: rntbd://cdb-ms-prod-northeurope1-fd8.documents.azure.com:14173/apps/.../, LSN: 304, GlobalCommittedLsn: 303, PartitionKeyRangeId: 0, IsValid: True, StatusCode: 200, SubStatusCode: 0, RequestCharge: 7.62, ItemLSN: -1, SessionToken: ..., UsingLocalLSN: False, TransportException: null"
}
],
"AddressResolutionStatistics": [],
"SupplementalResponseStatistics": [],
"FailedReplicas": [],
"RegionsContacted": [
"<redacted>"
],
"ContactedReplicas": [
"rntbd://cdb-ms-prod-northeurope1-fd8.documents.azure.com:14173/apps/<redacted>/",
"rntbd://cdb-ms-prod-northeurope1-fd8.documents.azure.com:14387/apps/<redacted>/",
"rntbd://cdb-ms-prod-northeurope1-fd8.documents.azure.com:14215/apps/<redacted>/",
"rntbd://cdb-ms-prod-northeurope1-fd8.documents.azure.com:14064/apps/<redacted>/"
]
}
},
{
"Id": "BatchAsyncContainerExecutor.ToResponse",
"ElapsedTime": "00:00:00.0000295"
}
]
}
您似乎在使用批量模式。请记住,批量模式是一种在发送大量操作时使 RU 饱和的模式。你提到你要发送 < 10,所以我建议(除非你有发送更多的情况)在这种情况下你不要使用批量模式。
另请检查:
- 您使用的是 Singleton CosmosClient 吗?
- 实例 运行 是否与您的写入 Cosmos DB 区域位于同一区域?
- 更新您的 SDK,您使用的是 3.6.0 版,在 3.11.0 中对 Bulk(如果您仍想使用 Bulk)进行了改进,使其在文档数量较少的情况下速度更快。