我正在测试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
}
答案 0 :(得分:2)
这可能有三个基础结构原因:
凭据缓存;收到初始连接后,服务器必须连接到身份验证服务器上的身份验证源并等待答复。收到回复后,将其缓存以备以后使用。
虚拟机启动;第一个请求启动一个新的VM实例,并在完成后处理该请求。
数据库集合;相关记录和索引是从后端数据库收集的,并缓存在分配的服务器上。如果在初始查询中使用了多个表和索引,这将变得更加明显。当服务器具有足够的信息来满足请求时,将发送结果。
后续查询将已经缓存了信息,因此将更快。
解决方案是先执行异步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);
}
}