首页 文章

有没有什么方法可以缓存Azure Cosmos DB的DocumentClient以获得更好的性能?

提问于
浏览
1

我正在开发一个常用的命令行工具,该工具由Azure Cosmos DB(SQL API版本)提供支持 . 它需要在启动后检查一些文档,我发现创建DocumentClient并找到该集合总共需要5秒钟 .

所以我想知道是否有任何解决方案可以在本地缓存DocumentClient或Database / DocumentCollection连接或其他方法来提高Cosmos DB的相关性能?

这是我的代码---我在谈论构造函数:

public static class CacheUtils
{
    private static readonly string DatabaseName = "myDatabase";
    private static readonly string CollectionName = "myLruCache";

    private static DocumentClient Client { get; }
    private static Database Database { get; }
    private static DocumentCollection DocumentCollection { get; }

    static CacheUtils()
    {
        var connectionPolicy = new ConnectionPolicy
        {
            EnableEndpointDiscovery = true,
            ConnectionMode = ConnectionMode.Direct,
            ConnectionProtocol = Protocol.Tcp,
            RequestTimeout = TimeSpan.FromSeconds(3),
            RetryOptions = new RetryOptions
            {
                MaxRetryAttemptsOnThrottledRequests = 3,
                MaxRetryWaitTimeInSeconds = 10
            }
        };

        Client = new DocumentClient(new Uri(myEndpoint), myAccessToken, connectionPolicy);
        Client.OpenAsync().GetResultSafe();

        Database = Client.CreateDatabaseIfNotExistsAsync(new Database {Id = DatabaseName}).GetResultSafe().Resource;
        DocumentCollection = Client.CreateDocumentCollectionIfNotExistsAsync(
            Database.SelfLink,
            new DocumentCollection {Id = CollectionName, DefaultTimeToLive = -1},
            new RequestOptions {OfferThroughput = 1000}).GetResultSafe().Resource;
    }

    // Omit CRUD operation wrappers
}

为了测量初始化过程的时间成本,添加了一个 Stopwatch

var s1 = new Stopwatch();
s1.Start();

Console.WriteLine($"[{s1.Elapsed.TotalSeconds:F3}] DocDB Start");
Client = new DocumentClient(new Uri(endpoint), accessToken, connectionPolicy);
Client.OpenAsync().GetResultSafe();
Console.WriteLine($"[{s1.Elapsed.TotalSeconds:F3}] DocDB Client Done");

Database = Client.CreateDatabaseIfNotExistsAsync(new Database { Id = DatabaseName }).GetResultSafe().Resource;
Console.WriteLine($"[{s1.Elapsed.TotalSeconds:F3}] DocDB DB Done");

DocumentCollection = Client.CreateDocumentCollectionQuery(Database.SelfLink).Where(c => c.Id == CollectionName).ToList().FirstOrDefault();
Console.WriteLine($"[{s1.Elapsed.TotalSeconds:F3}] DocDB Coll Done");

跑了三次:

# 1
[0.000] DocDB Start
[3.064] DocDB Client Done
[3.143] DocDB DB Done
[3.363] DocDB Coll Done

# 2
[0.000] DocDB Start
[2.256] DocDB Client Done
[2.314] DocDB DB Done
[2.617] DocDB Coll Done

# 3
[0.000] DocDB Start
[2.684] DocDB Client Done
[2.788] DocDB DB Done
[3.331] DocDB Coll Done

1 回答

  • 2

    您可以将DocumentClient存储到静态变量中,并在应用程序实例中重复使用它 . 例如 .

    public class CosmosDbRepo : ICosmosDbRepo
    {
       private static DocumentClient _cosmosDocumentClient; 
       public CosmosDbRepo(IDatabaseFactory databaseFactory, CosmosDbConnectionParameters cosmosDbConnectionParameters)
        {           
            _collectionUri = UriFactory.CreateDocumentCollectionUri(cosmosDbConnectionParameters.DatabaseId, cosmosDbConnectionParameters.CollectionId);
    
            if (_cosmosWriteDocumentClient == null)
            {
                _cosmosDocumentClient = databaseFactory.CreateDbConnection(cosmosDbConnectionParameters, ConnectionMode.Direct).DocumentClient;
            }
        }
    }
    

    然后,_cosmosDocumentClient可以由您的应用的多个实例使用 .

    我目前正在开发一个使用这种静态cosmosdb连接的Azure功能应用程序 . Azure功能应用程序的实例共享静态对象 .

    如果运行然后关闭命令行程序,则每次程序启动时都必须重新创建静态连接,并且不会从静态连接中获得太多好处 . 让程序连续运行会有所帮助 . 您可能有多个线程处理多个工作单元实例,这些实例处理您的程序所执行的作业,并且这些多个实例可以共享静态cosmos数据库连接 .

相关问题