Azure Functions结合Azure Cosmos DB或SQL数据库时负载测试性能异常排查求助
从你的描述和代码来看,每次请求都重新初始化Cosmos Client是导致负载下响应变慢的核心原因,这也是Azure Functions + Cosmos DB场景中常见的性能陷阱。下面给你具体的排查方向和优化方案:
1. 修复Cosmos Client的初始化方式
你的代码里,每次处理/postcode_cosmosdb请求时都会新建一个CosmosClient实例,而Cosmos Client的初始化是相对重的操作——它会建立连接池、初始化认证等。在高负载下,频繁创建销毁客户端会导致大量的连接开销,直接拖慢响应时间。
Cosmos Client是线程安全且设计为复用的,应该把它的初始化移到函数的全局作用域(模块级别),这样整个函数实例的所有请求都会复用同一个客户端和连接池。修改后的代码如下:
import azure.functions as func import os from azure.functions import AsgiMiddleware from fastapi import Query from typing import Optional from api_app import app import azure.cosmos.documents as documents import azure.cosmos.cosmos_client as cosmos_client import azure.cosmos.exceptions as exceptions from azure.cosmos.partition_key import PartitionKey # 全局初始化Cosmos Client,仅在函数实例启动时执行一次 settings = { 'host': os.environ.get('ACCOUNT_HOST', 'XXXXXX'), 'master_key': os.environ.get('ACCOUNT_KEY', 'XXXXXX'), 'database_id': os.environ.get('COSMOS_DATABASE', 'WoningAdressen'), 'container_id': os.environ.get('COSMOS_CONTAINER', 'AdressenLight'), } HOST = settings['host'] MASTER_KEY = settings['master_key'] DATABASE_ID = settings['database_id'] CONTAINER_ID = settings['container_id'] # 全局客户端实例,复用连接池 client = cosmos_client.CosmosClient(HOST, {'masterKey': MASTER_KEY}, user_agent="CosmosDBPythonQuickstart", user_agent_overwrite=True) db = client.get_database_client(DATABASE_ID) container = db.get_container_client(CONTAINER_ID) @app.get("/status") def get_status(): return ({"status": 200}) @app.get("/postcode_cosmosdb/{postcode}/{huisnummer}") async def postcode_cosmosdb(postcode: str, huisnummer: int): items = list(container.query_items( query="SELECT l.postcode, l.huisnummer, l.huisletter, l.nummeraanduiding_id as bagid, l.gemeente FROM AdressenLight as l WHERE l.postcode=@postcode AND l.huisnummer=@huisnummer", parameters=[ { "name":"@postcode", "value": postcode }, { "name":"@huisnummer", "value": huisnummer } ] )) return items def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse: return AsgiMiddleware(app).handle(req, context)
2. 排查数据库连接池与资源限制
- Cosmos DB侧:检查你的容器是否有足够的请求单位(RU)。虽然CPU内存正常,但如果负载下RU使用率接近100%,会导致请求被节流(Cosmos会自动重试,但会增加耗时)。可以在Azure Portal查看Cosmos DB的
Total Request Units指标。 - Azure Functions侧:如果使用的是Consumption计划,函数实例会自动扩展,但每个实例的并发请求数默认是100。你可以在
host.json中调整maxConcurrentRequests参数,比如:
如果是Premium计划,还可以调整实例的数量和规格,获得更稳定的性能。{ "version": "2.0", "functionTimeout": "00:05:00", "extensions": { "http": { "maxConcurrentRequests": 100 } } }
3. 优化查询性能
即使数据库资源正常,查询本身也可能存在优化空间:
- 检查分区键:如果你的Cosmos容器分区键不是
postcode或postcode+huisnummer,那么当前的查询会是跨分区查询,这会消耗更多RU且变慢。建议将分区键设置为查询中频繁使用的字段组合,比如postcode。 - 创建覆盖索引:确保你的查询用到的字段(
postcode、huisnummer)有索引,并且投影的字段(huisletter、bagid、gemeente)也被包含在索引中,避免Cosmos进行全表扫描。
4. 用监控工具定位瓶颈
- 使用Application Insights追踪每个请求的详细耗时,看数据库调用的阶段是否在负载下明显变长,这能帮你确认是连接问题还是查询本身的问题。
- 在Azure Monitor中查看函数的
Connections指标,看是否有连接数飙升的情况;同时查看Cosmos DB的Connection Pool Size指标,确认连接池是否被有效复用。
按照这个顺序排查,先解决客户端初始化的问题,应该能大幅改善负载下的响应时间。
内容的提问来源于stack exchange,提问作者Joey
相关产品推荐
相关产品推荐

