Discord机器人连接MongoDB保存数据报DNS超时错误
问题背景
开发Discord服务器需支持人员审批的角色分配系统,核心逻辑需要持久化存储待审批申请对应的消息ID、申请发起用户ID,目前非数据库相关业务逻辑运行正常,数据库相关代码启动即报错。
相关代码
业务事件代码
cluster = MongoClient('mongodb+srv://corry:pa4-pD6-3Dj-AdT@cluster0.gi8x6.mongodb.net/?retryWrites=true&w=majority') db = cluster.RolesData roles = db.RolesCollection @bot.event async def on_message(message): msg = message.content.lower() request = ['роль', 'хочу роль', 'дайте роль', 'нужна роль'] if msg in request: for i in orgs: if not message.author.display_name.split(' ')[0].replace('[', '') in orgs: await message.channel.send(f'`[ROLES]`: {message.author.mention}, тег организации не найден!') break if i == message.author.display_name.split(' ')[0].replace('[', ''): guild = bot.get_guild(831511376425123882) role = discord.utils.get(guild.roles, id=orgs[i]) await message.channel.send(f'`[ROLES]`: {message.author.mention}, ваш запрос на получение роли был отправлен саппортам!') embed = discord.Embed( title='Запрос на получение роли!', description='✅ - выдать роль\n❌ - отклонить запрос\n🖊️ - изменить никнейм\n📋 - запросить статистику', color=0x000000 ) embed.add_field(name=f'Пользователь:', value=f'{message.author.mention}', inline=False) embed.add_field(name=f'Никнейм:', value=f'{message.author.display_name}', inline=False) embed.add_field(name=f'Роль для выдачи:', value=f'{role.mention}', inline=False) embed.set_thumbnail(url='https://psv4.userapi.com/c537232/u356224017/docs/d1/416eb92aec38/rodina.png?extra=2E9CwKZ0PIjnG8aaNkwehlHwjxlycBfGx-4p20ABm3mPI4jNpdV1OXaUUA9zGA4Q04VM21UezrXsjtqC411Xbh-Ro7rW1L4OGgNxpcQv3lvfOYCb-Irn-_-51AaQa2fpNDZhHm80dvZm1HlR1ZWoDigw') embed.set_image(url=message.author.avatar_url) msgemb = await bot.get_channel(851413212485779466).send(embed=embed) await msgemb.add_reaction('✅') await msgemb.add_reaction('❌') await msgemb.add_reaction('🖊️') await msgemb.add_reaction('📋') roles_post = { 'm_id':msg_db.id, 'user':msg_db.author } if roles.count_documents({'m_id':message.id}) == 0: roles.insert_one(roles_post) else: await message.channel.send(f'`[ROLES]`: {message.author.mention}, вы уже отправили запрос на получение роли!')
报错输出
Traceback (most recent call last): File "C:\Users\Хозяин\AppData\Local\Programs\Python\Python39\lib\site-packages\pymongo\srv_resolver.py", line 89, in _resolve_uri results = _resolve( File "C:\Users\Хозяин\AppData\Local\Programs\Python\Python39\lib\site-packages\pymongo\srv_resolver.py", line 43, in _resolve return resolver.resolve(*args, **kwargs) File "C:\Users\Хозяин\AppData\Local\Programs\Python\Python39\lib\site-packages\dns\resolver.py", line 1305, in resolve return get_default_resolver().resolve(qname, rdtype, rdclass, tcp, source, File "C:\Users\Хозяин\AppData\Local\Programs\Python\Python39\lib\site-packages\dns\resolver.py", line 1176, in resolve timeout = self._compute_timeout(start, lifetime) File "C:\Users\Хозяин\AppData\Local\Programs\Python\Python39\lib\site-packages\dns\resolver.py", line 997, in _compute_timeout raise Timeout(timeout=duration) dns.exception.Timeout: The DNS operation timed out after 21.201510190963745 seconds During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Users\Хозяин\Desktop\rodina\main.py", line 5, in <module> cluster = MongoClient('mongodb+srv://corry:pa4-pD6-3Dj-AdT@cluster0.gi8x6.mongodb.net/?retryWrites=true&w=majority') File "C:\Users\Хозяин\AppData\Local\Programs\Python\Python39\lib\site-packages\pymongo\mongo_client.py", line 704, in __init__ res = uri_parser.parse_uri( File "C:\Users\Хозяин\AppData\Local\Programs\Python\Python39\lib\site-packages\pymongo\uri_parser.py", line 542, in parse_uri nodes = dns_resolver.get_hosts() File "C:\Users\Хозяин\AppData\Local\Programs\Python\Python39\lib\site-packages\pymongo\srv_resolver.py", line 121, in get_hosts _, nodes = self._get_srv_response_and_hosts(True) File "C:\Users\Хозяин\AppData\Local\Programs\Python\Python39\lib\site-packages\pymongo\srv_resolver.py", line 101, in _get_srv_response_and_hosts results = self._resolve_uri(encapsulate_errors) File "C:\Users\Хозяин\AppData\Local\Programs\Python\Python39\lib\site-packages\pymongo\srv_resolver.py", line 97, in _resolve_uri raise ConfigurationError(str(exc)) pymongo.errors.ConfigurationError: The DNS operation timed out after 21.201510190963745 seconds Для продолжения нажмите любую клавишу . . .
问题定位
- 启动阶段初始化
MongoClient连接MongoDB Atlas集群失败,根因是DNS解析操作超时,抛出pymongo.errors.ConfigurationError异常,程序直接终止 - 业务逻辑中存在未定义变量引用:代码中从未声明
msg_db变量,即使数据库连接正常,运行到存储申请记录的逻辑时也会触发NameError - 存储逻辑存在设计缺陷:直接存储Discord实体对象会导致序列化异常,重复申请校验维度错误,无法正确拦截同一用户的重复提交
修复方案
1. 解决MongoDB连接DNS超时问题
按优先级依次排查处理:
- 检查网络拦截规则:确认本地防火墙、系统代理、网络运营商没有拦截对MongoDB Atlas域名的解析和访问,临时关闭防火墙/代理测试连通性
- 更换本地DNS配置:将系统默认DNS修改为公共DNS(如223.5.5.5、119.29.29.29、8.8.8.8),刷新本地DNS缓存后重试
- 校验Atlas集群配置:登录MongoDB Atlas控制台,确认集群处于正常运行状态,当前客户端出口公网IP已加入集群IP白名单,数据库账号密码具备对应集合的读写权限
- 重装兼容版本依赖:执行以下命令安装稳定版pymongo和DNS解析依赖,避免版本兼容问题
pip uninstall -y pymongo dnspython pip install pymongo[srv]==4.6.3 dnspython==2.6.1
2. 修复业务代码逻辑bug
将存储申请记录部分的代码替换为以下内容,修正未定义变量问题、存储字段问题和重复校验逻辑:
# 发送审批嵌入消息、添加反应完成后 roles_post = { 'approval_msg_id': msgemb.id, # 存储审批频道消息ID,用于后续反应事件匹配 'applicant_user_id': message.author.id, # 存储申请人用户ID,不要直接存用户对象 'target_role_id': role.id, # 额外存储待分配角色ID,方便后续审批逻辑直接使用 'apply_time': message.created_at } # 校验当前用户是否存在待处理申请,避免重复提交 if roles.count_documents({'applicant_user_id': message.author.id, 'status': 'pending'}) == 0: roles.insert_one(roles_post) else: await message.channel.send(f'`[ROLES]`: {message.author.mention}, вы уже отправили запрос на получение роли!')
内容的提问来源于stack exchange,提问作者Corrygan
相关产品推荐
相关产品推荐

