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

时间:2018-08-10 16:48:03

标签: c# .net azure caching azure-cosmosdb

我正在开发一个常用的命令行工具,该工具由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");

运行3次:

# 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 个答案:

答案 0 :(得分: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 db连接。