简体   繁体   中英

Any ways to cache DocumentClient of Azure Cosmos DB for better performance?

I'm developing a frequently used command line tool which is powered by Azure Cosmos DB (SQL API version). It needs to check a few documents just after the launch, and I found that creating DocumentClient and finding the very collection will take up to 5 seconds in total.

So I'm wondering if there's any solutions to cache the DocumentClient or Database/DocumentCollection connections locally or other ways to improve the Cosmos DB related performance?

Here's my code --- I'm talking about the constructor:

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
}

To measure the time cost of the initialization process, a Stopwatch was added:

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");

Ran it three times:

# 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

You can store DocumentClient into a static variable and reuse it across app instances. Eg

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 can then be used by multiple instances of your app.

I am currently developing an Azure function app that uses such static cosmosdb connection. Azure function app's instances share the static objects.

If you run and then shutdown the command line program, the static connection will have to be recreated each time the program starts up and you don't get much benefit out of static connection. Make the program running continuously will help. You may have multiple threads handling multiple instances of work units that deal with the jobs your program does, and these multiple instances can share the static cosmos db connection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM