如何在AWS Lambda中使用PyMongo实现MongoDB连接池?
解决AWS Lambda + PyMongo + MongoDB Atlas的连接数持续增长问题
问题根源
你当前的代码每次调用lambda_handler时都会新建一个MongoClient实例,而AWS Lambda的执行环境存在热复用机制——当请求结束后,执行环境不会立刻销毁,后续请求可能会复用这个环境。这就导致每次复用环境时,旧的MongoClient还在,新的又被创建,每个Client都自带独立的连接池,最终MongoDB的连接数会持续累积直到达到上限。
其实PyMongo的MongoClient本身就内置了连接池管理能力,核心问题是不能让Client随每次函数调用重复创建,要让它在Lambda执行环境中复用。
解决方案:全局初始化MongoClient
把MongoClient的初始化代码移到lambda_handler函数的全局作用域,这样只有第一次冷启动时会创建Client,后续热启动的请求都会复用这个已存在的Client,连接池也能被正确管理。
修改后的完整代码示例:
import json from bson import json_util from pymongo import MongoClient # 全局作用域初始化:仅在Lambda冷启动时创建一次Client client = MongoClient('mongodb+srv://app_user:123456@accesdev-dxjpa.mongodb.net/test') db = client.test def lambda_handler(event, context): print("Received event: " + json.dumps(event, indent=1)) user_profile = db.user_profile email = event['email'] # 简化邮箱/用户名的判断逻辑 if '@' not in email: user_data = list(user_profile.find({"username": email}, {"name": 1, "photo": 1, "bio": 1})) else: user_data = list(user_profile.find({"email": email}, {"name": 1, "photo": 1, "bio": 1})) # 简化序列化流程,无需先dump再load return json.loads(json_util.dumps(user_data))
额外优化建议
- 自定义连接池参数:根据你的并发需求,手动配置连接池的大小和闲置超时,避免连接池过大或闲置连接占用资源:
client = MongoClient( 'mongodb+srv://app_user:123456@accesdev-dxjpa.mongodb.net/test', maxPoolSize=10, # 连接池最大连接数 minPoolSize=0, maxIdleTimeMS=30000 # 闲置30秒的连接自动关闭 ) - 处理连接失效:如果Lambda执行环境闲置过久,MongoDB的连接可能会被Atlas负载均衡器断开,不过PyMongo的
MongoClient会自动尝试重连,一般无需额外处理;若遇到偶发连接错误,可在函数内添加简单的重试逻辑。 - 简化序列化步骤:原代码中
json.dumps后再json.loads是多余的,直接用json_util.dumps序列化后再转成JSON对象返回即可。
原代码的小细节修正
原代码用res = Email.find('@')判断是否为邮箱,其实直接用if '@' not in email更直观,也避免了索引判断的潜在逻辑问题。
内容的提问来源于stack exchange,提问作者Ramesh Reddy




