Azure Function + Cosmos DB 和静态客户端

Azure Function + Cosmos DB and Static clients

对于许多人来说,这可能是一个非常明显的问题。但对我来说不是。

我目前正在研究具有 azure 函数的 cosmos DB 的性能。显而易见的解决方案之一是创建静态客户端。工作正常。

在当前架构中,我在同一个实例中为每个客户设置了 Cosmos DB。所以,我想我可以对不同的数据库 ID 及其各自的容器使用相同的 cosmos 客户端。如果我有多个端点和它们的数据库以及它们自己的容器怎么办。我如何确保为这种情况设置了静态客户端。

请注意,我们计划提供两种类型的订阅,一种是共享资源,另一种是专用。

您可以使用 Azure Functions DI 而不是静态客户端:https://github.com/Azure/azure-cosmos-dotnet-v3/tree/master/Microsoft.Azure.Cosmos.Samples/Usage/AzureFunctions

注入服务,在内部维护 ConcurrentDictionary 或某些结构,每个帐户都有一个客户列表。

Azure Functions 使用此服务并向客户请求帐户,该服务将获取或添加客户到内部列表。

该服务作为单例维护,因此内部客户端列表也是单例,您使用的每个帐户只有 1 个客户端。

示例(请不要照字面意思理解这段代码):

public class CosmosService
{
    private ConcurrentDictionary<string, CosmosClient> clients = new ConcurrentDictionary<string, CosmosClient>();

    public CosmosClient GetClientForEndpoint(string connectionString (or whatever account identifier you want) ) 
    {
        if (clients.TryGetValue(connectionString, out CosmosClient client)) 
        {
            return client;
        }
    
        CosmosClient newClient = new CosmosClient(connectionString, (add whatever CosmosClientOptions you want here));
        
        if (!clients.TryAdd(connectionString, newClient))
        {
            // Another concurrent thread added a client for the same key
            newClient.Dispose(); // Avoid leaks
            if (clients.TryGetValue(connectionString, out CosmosClient client)) 
            {
                return client;
            }
            
            throw new InvalidOperationException("Reaching here means something removed the client instance");
        }
        
        return newClient;
    }
}

然后您可以在函数初始化期间将其存储为单例 (https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/Microsoft.Azure.Cosmos.Samples/Usage/AzureFunctions/Startup.cs)

并且在您的函数上,您可以获取 CosmosService,为租户使用的 account/connection 调用 GetClientForEndpoint(在管理多个帐户的情况下),然后获取该帐户的实例。

如果您需要为不同的帐户维护多个客户端,那么您将共享客户端实例,这是按照单例模式完成的(在应用程序的生命周期内每个帐户一个客户端)。