Azure中并行查询的CosmosDB SocketException



我们在Azure中有一个web应用程序(asp.net core 3.1(,用于查询CosmosDB数据库(具有自动缩放功能(。出于性能原因,我通过首先创建一个Task<data>数组,然后运行Task.WhenAll(..)来发送查询,来并行处理所有查询。当数组变得太大(~3000(时,我经常会得到一个SocketException。问题是,这是随机的,因为我从来没有在我的本地开发PC上得到过这个,当它工作时,在Azure中,数据会在几秒钟后返回。

I Application Insights,失败的查询显示为

  • 第一个有200个响应,持续时间约为100毫秒
  • 然后我可以有一些200个响应,持续4-5秒
  • 然后是持续时间约为20秒的故障

我看到人们唯一推荐的CosmosDB客户端设置是这样的:

client = new DocumentClient(
new Uri(..), 
Key,
new ConnectionPolicy()
{
ConnectionMode = ConnectionMode.Direct,
ConnectionProtocol = Protocol.Tcp,
IdleTcpConnectionTimeout = new TimeSpan(0, 10, 0, 0)
});

其他哪些设置可能相关?我玩过MaxRequestsPerTcpConnection = 16OpenTcpConnectionTimeout = new TimeSpan(0, 1, 0, 0)RequestTimeout = new TimeSpan(0, 1, 0, 0),但似乎都没有效果。

更新2020-10-24:

连接的数量可能会限制并行连接,但我不知道如何以简单的方式处理这一问题,因为有时查询会运行良好,有时则不然。

然而,解决方案是避免手动并行,并让CosmosDB以任何优化的方式处理这一问题。我写这些并行查询已经很长时间了,这可能是性能和RU/s之间的权衡,因为查询是跨分区的。代码必须处理427个错误,但当我转到自动缩放时,这个错误被删除了。并行代码现在被重写为跨分区,最大并发量=-1,参考并行跨分区查询。

代码方面,第一个查询是:

var query = client.CreateDocumentQuery<MyClass>(
UriFactory.CreateDocumentCollectionUri(db, collection),
new FeedOptions 
{ 
MaxItemCount = -1 
})
.Where(q => q.PartitionKey == partitionKey)
.AsDocumentQuery();

我将其添加到每个分区键的任务列表中。

然后是交叉分区:

var partitionKeys = <list of partition keys>; 
var query = client.CreateDocumentQuery<MyClass>(
UriFactory.CreateDocumentCollectionUri(db, collection),
new FeedOptions
{
MaxItemCount = -1,
EnableCrossPartitionQuery = true,
MaxDegreeOfParallelism = -1
})
.Where(q => partitionKeys.Contains(q.PartitionKey))
.AsDocumentQuery();

您可能会遇到Azure应用程序服务对同时连接的限制:

每个实例的最大IP连接数取决于实例大小:每个B1/S1/P1V3实例1920个,每个B2/S2/P2V3实例3968个,8064每个B3/S3/P3V3实例

因此,增加实例大小可能会有所帮助。但这需要管理大量的联系,扩大规模并不一定是最好的方法。在SDK中使用批量支持应该有助于整合这些同时连接:

https://devblogs.microsoft.com/cosmosdb/introducing-bulk-support-in-the-net-sdk/

最新更新