CosmosDb的第一次连接可能花费很多秒

时间:2019-05-24 15:36:39

标签: azure-cosmosdb

我正在测试CosmosDb。我发现初始连接通常需要花费几秒钟的时间。我编写了一个小型的.net core 2.2控制台应用程序来演示该问题。

   static async System.Threading.Tasks.Task Main(string[] args)
    {
        Console.WriteLine("Hello World!");
        string url = "https://docdb.documents.azure.com:443/";
        string key = "myKey";
        DocumentClient docClient = new DocumentClient(new Uri(url), key);
        Stopwatch sw = new Stopwatch();
        while (true)
        {
            sw.Start();
            var res = await docClient.ReadDocumentAsync(UriFactory.CreateDocumentUri("ct", "ops", "xxx"),
                new RequestOptions { PartitionKey = new Microsoft.Azure.Documents.PartitionKey("test") });
            sw.Stop();
            Console.WriteLine($"Query took {sw.ElapsedMilliseconds}ms");
            sw.Reset();
           await Task.Delay(1000);
        }
    }

这是我的典型结果:

Hello World!
Query took 48530ms
Query took 36ms
Query took 26ms
Query took 15ms

第一个请求需要48秒!我试图将docClient结构修改为:

 DocumentClient docClient = new DocumentClient(new Uri(url), key,new 
 ConnectionPolicy {ConnectionMode = ConnectionMode.Direct,ConnectionProtocol 
 = Protocol.Tcp });

查看一些典型结果是否更好:

 Hello World!
Query took 20536ms
Query took 104ms
Query took 37ms
Query took 71ms
Query took 13ms
Query took 88ms
Query took 14ms

第一次查询仍然需要20秒。

我的数据库是

130Mb     
Avg Throughput /s*  3.58 RU/s

我有

 400 RU's 

我有什么办法可以减轻第一次连接的延迟?

我在Cosmosdb上的文档是:

 {
"id": "xxx",
"fid": "test",
"_rid": "VX8TAPKGDqNeWwEAAAAAAA==",
"_self": "dbs/VX8TAA==/colls/VX8TAPKGDqM=/docs/VX8TAPKGDqNeWwEAAAAAAA==/",
"_etag": "\"0000d4a2-0000-1100-0000-5ce801ef0000\"",
"_attachments": "attachments/",
"_ts": 1558708719
}

2 个答案:

答案 0 :(得分:2)

这可能有三个基础结构原因:

  1. 凭据缓存;收到初始连接后,服务器必须连接到身份验证服务器上的身份验证源并等待答复。收到回复后,将其缓存以备以后使用。

  2. 虚拟机启动;第一个请求启动一个新的VM实例,并在完成后处理该请求。

  3. 数据库集合;相关记录和索引是从后端数据库收集的,并缓存在分配的服务器上。如果在初始查询中使用了多个表和索引,这将变得更加明显。当服务器具有足够的信息来满足请求时,将发送结果。

后续查询将已经缓存了信息,因此将更快。

解决方案是先执行异步null查询(一个不执行任何操作的小请求),而无需等待结果,从而为系统实际的即将到来的查询做好准备。

取决于应用程序,您可能希望在长时间不活动期间发送保持活动请求。根据费用结构,这可能会变得昂贵。

有很多因素在起作用(其中大部分是您无法控制的):分区中数据的大小和数量,关键组织和索引,服务器负载,网络拥塞,数据碎片,缓存策略,存储层(热-立即访问和快速传输(SSD或内存),热-立即访问和慢速传输(HDD),冷-延迟访问和慢速传输(关闭HDD))。

这通常是基于云的技术的主要缺点。您将轻微延迟和控制风险权衡以获取可用性和弹性。

答案 1 :(得分:2)

这是预期的,请参阅https://docs.microsoft.com/en-us/azure/cosmos-db/performance-tips#networking中的#2点

  

默认情况下,第一个请求具有更高的延迟,因为它必须获取地址路由表。为了避免在第一个请求上出现启动延迟,您应该在初始化期间如下调用一次OpenAsync()。

static async System.Threading.Tasks.Task Main(string[] args)
{
    Console.WriteLine("Hello World!");
    string url = "https://docdb.documents.azure.com:443/";
    string key = "myKey";
    DocumentClient docClient = new DocumentClient(new Uri(url), key);
    await docClient.OpenAsync();
    Stopwatch sw = new Stopwatch();
    while (true)
    {
        sw.Start();
        var res = await docClient.ReadDocumentAsync(UriFactory.CreateDocumentUri("ct", "ops", "xxx"),
            new RequestOptions { PartitionKey = new Microsoft.Azure.Documents.PartitionKey("test") });
        sw.Stop();
        Console.WriteLine($"Query took {sw.ElapsedMilliseconds}ms");
        sw.Reset();
       await Task.Delay(1000);
    }
}