PyMongo默认不自动重试连接失败,需手动封装初始化逻辑并区分可重试异常(如ServerSelectionTimeoutError),推荐用tenacity实现指数退避重试,同时对运行时操作兜底重试并配置健康检查与日志。

连接失败时 PyMongo 默认不重试,得手动控制
PyMongo 4.x+ 默认关闭服务器端重试(retryWrites=False),且网络断开、主节点切换等场景下,client 不会自动重建连接——它只是“懒惰地”在下次操作时尝试重连,但若首次连接就失败(比如 MongoDB 服务未启动),MongoClient 初始化就会抛出 ConnectionFailure 或 ServerSelectionTimeoutError,不重试。
所以必须自己封装初始化逻辑,不能依赖驱动内置行为。
- 重试不是加个
while True就行:要区分错误类型,比如认证失败(OperationFailure)重试没用,而连接超时(ServerSelectionTimeoutError)才值得重试 - 建议用指数退避(exponential backoff),避免密集探测压垮网络或触发防火墙限流
-
maxPoolSize和minPoolSize不影响初始连接,只影响后续连接池管理,别误以为设了就能“自动恢复”
用 tenacity 实现带策略的重试最稳妥
手写 try/except/time.sleep 容易漏掉边界条件(比如重试次数上限、异常分类、jitter 防抖)。直接用 tenacity 库更可靠,它专为这类场景设计。
安装:pip install tenacity
立即学习“Python免费学习笔记(深入)”;
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
from pymongo import MongoClient
from pymongo.errors import ServerSelectionTimeoutError, ConnectionFailure
<p>@retry(
stop=stop_after_attempt(5),
wait=wait_exponential(multiplier=1, min=1, max=10),
retry=retry_if_exception_type((ServerSelectionTimeoutError, ConnectionFailure))
)
def get_mongo_client():
return MongoClient("mongodb://localhost:27017/", serverSelectionTimeoutMS=2000)</p><h1>使用</h1><p>client = get_mongo_client()
db = client["mydb"]-
serverSelectionTimeoutMS=2000必须显式设小一点,否则默认 30s,重试间隔会严重失真 -
retry_if_exception_type里只放可重试的异常,别把InvalidURI或ConfigurationError加进去——那是配置问题,重试无意义 - 第一次调用
get_mongo_client()就会触发重试逻辑,不是等到执行db.collection.find_one()才开始
连接成功后,还要防运行时连接中断
即使初始化成功,运行中也可能因网络抖动、副本集主节点切换、防火墙断连导致后续操作失败。这时不能只靠初始化重试,得在业务操作层加兜底。
- 对关键读写操作(如
collection.insert_one()),同样用@retry包裹,但异常类型换成AutoReconnect、NotPrimaryError、NetworkTimeout - 注意:PyMongo 4.0+ 已弃用
AutoReconnect,改用ConnectionFailure和NotPrimaryError,检查你用的版本 - 不要在每次
find()前都新建client——连接对象是线程安全且自带连接池,复用即可;频繁新建反而加重握手负担
生产环境必须配健康检查和日志上下文
光重试不够,得知道为什么重试、重试了几次、最终是否成功。否则出问题时只能看报错,没法定位是网络问题还是权限问题。
- 在
@retry的before和after钩子里打日志,记录重试序号、异常类型、当前等待秒数 - 加一个轻量健康检查接口(如
client.admin.command("ping")),供监控系统轮询,比单纯 ping 端口更能反映 MongoDB 实际可用性 - 如果用 Docker/K8s,注意
localhost在容器内指向自身,连接宿主机 MongoDB 要用host.docker.internal(Mac/Win)或宿主机真实 IP(Linux)
重试逻辑本身不难,难的是判断该不该重、重几次、重完怎么反馈——这些细节不处理好,自动重试反而掩盖真实故障点。


















