Azure无服务器函数应用中CosmosClient连接管理问题求助
问题
微软建议在整个应用中维护单个CosmosClient实例,我在Azure无服务器Python函数应用里尝试这么做(不止是CosmosClient),但就算复用数据库和容器代理,请求量一大就收到警告:已达Cosmos最大连接数(10个),正在丢弃连接。
背景:这是个由消息队列触发的无服务器Python函数应用,连接通过辅助函数里的共享代码管理,必须用Cosmos SDK来读写文档。
想问有没有人解决过这类问题?为每个函数调用实例化新连接是不是最佳实践?我试过在突发流量时创建新CosmosClient,但很难高效实现。
下面是我用来管理连接的类示例:
COSMOS_CLIENT = None class Client: def __init__(self): self.cosmos_client: CosmosClient = self._get_global_cosmos_client() def _get_global_cosmos_client() -> CosmosClient: global COSMOS_CLIENT if COSMOS_CLIENT is None: logging.info('[COSMOS] NEW CLIENT CONNECTION') COSMOS_CLIENT = CosmosClient.from_connection_string(COSMOS_DB_CONNECTION_STRING) return COSMOS_CLIENT
解决方案
- 绝对不要为每个函数调用实例化新连接:这会快速耗尽Cosmos的连接配额,反而加剧问题。单实例复用是正确方向,但要适配Azure函数的运行时特性。
- 显式调整CosmosClient的连接池配置:默认配置可能不匹配无服务器场景,初始化时自定义连接策略参数:
from azure.cosmos import CosmosClient, ConnectionPolicy def _get_global_cosmos_client() -> CosmosClient: global COSMOS_CLIENT if COSMOS_CLIENT is None: logging.info('[COSMOS] NEW CLIENT CONNECTION') policy = ConnectionPolicy() policy.max_connection_limit = 10 # 不要超过Cosmos账户的配额,可按需微调 policy.idle_connection_timeout = 30 # 缩短空闲连接超时,快速释放闲置资源 COSMOS_CLIENT = CosmosClient.from_connection_string(COSMOS_DB_CONNECTION_STRING, connection_policy=policy) return COSMOS_CLIENT - 复用数据库与容器代理实例:不要每次请求都重新获取数据库、容器对象,将它们也设为全局变量复用:
COSMOS_CLIENT = None COSMOS_DB = None COSMOS_CONTAINER = None class Client: def __init__(self): self.cosmos_client = self._get_global_cosmos_client() self.db = self._get_global_db() self.container = self._get_global_container() def _get_global_cosmos_client() -> CosmosClient: global COSMOS_CLIENT if COSMOS_CLIENT is None: logging.info('[COSMOS] NEW CLIENT CONNECTION') policy = ConnectionPolicy() policy.max_connection_limit = 10 policy.idle_connection_timeout = 30 COSMOS_CLIENT = CosmosClient.from_connection_string(COSMOS_DB_CONNECTION_STRING, connection_policy=policy) return COSMOS_CLIENT def _get_global_db(self): global COSMOS_DB if COSMOS_DB is None: COSMOS_DB = self.cosmos_client.get_database_client(DATABASE_NAME) return COSMOS_DB def _get_global_container(self): global COSMOS_CONTAINER if COSMOS_CONTAINER is None: COSMOS_CONTAINER = self.db.get_container_client(CONTAINER_NAME) return COSMOS_CONTAINER - 接受Azure函数的横向扩展特性:当函数应用横向扩展出多个实例时,每个实例会持有自己的
COSMOS_CLIENT,这是正常现象,每个实例的连接数独立计算,不会互相占用配额。 - 排查连接泄漏:检查代码中是否有未正确收尾的操作,比如异步请求未处理完成、长期持有资源的逻辑,导致连接池无法回收连接。
- 调整Cosmos账户配额(按需):如果业务确实需要更高连接数,可在Azure门户中调整Cosmos账户的连接配额,但这会带来额外成本。
内容的提问来源于stack exchange,提问作者Hunter Boyd
相关产品推荐
相关产品推荐

