You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在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

火山引擎 最新活动